<!DOCTYPE html>



  


<html class="theme-next gemini use-motion" lang="zh-Hans">
<head><meta name="generator" content="Hexo 3.8.0">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">
















  
  
  <link href="/limh/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css">







<link href="/limh/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css">

<link href="/limh/css/main.css?v=5.1.4" rel="stylesheet" type="text/css">


  <link rel="apple-touch-icon" sizes="180x180" href="/limh/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/limh/images/favicon-32x32-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/limh/images/favicon-16x16-next.png?v=5.1.4">


  <link rel="mask-icon" href="/limh/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="教程,">










<meta name="description" content="5.2.1 数据传送指令数据传送指令又分为：传送指令、交换指令、地址传送指令、堆栈操作指令、转换指令和I/O指令等。 除了标志位操作指令SAHF和POPF指令外，本类的其它指令都不影响标志位。 1、传送指令MOV(Move Instruction)传送指令是使用最频繁的指令，它相对于高级语言里的赋值语句。指令的格式如下： 1MOV   Reg/Mem, Reg/Mem/Imm 其中：Reg—Reg">
<meta name="keywords" content="教程">
<meta property="og:type" content="article">
<meta property="og:title" content="5.2 指令系统">
<meta property="og:url" content="https://tdnr.gitee.io/limh/2015/04/01/asm22/index.html">
<meta property="og:site_name" content="土逗牛肉">
<meta property="og:description" content="5.2.1 数据传送指令数据传送指令又分为：传送指令、交换指令、地址传送指令、堆栈操作指令、转换指令和I/O指令等。 除了标志位操作指令SAHF和POPF指令外，本类的其它指令都不影响标志位。 1、传送指令MOV(Move Instruction)传送指令是使用最频繁的指令，它相对于高级语言里的赋值语句。指令的格式如下： 1MOV   Reg/Mem, Reg/Mem/Imm 其中：Reg—Reg">
<meta property="og:locale" content="zh-Hans">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0004.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image001_0023.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0006.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image001_0024.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0007.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image001_0025.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0008.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image001_0032.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0009.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image001_0060.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0010.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image001_0061.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0011.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0012.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image003_0004.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image001_0064.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0013.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image001_0065.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0014.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image001_0066.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0015.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image001_0067.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0016.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0022.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image003_0010.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image004_0001.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image005_0000.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image006_0000.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image007_0000.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image001_0081.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0023.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image003_0011.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image004_0002.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image005_0001.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image008_0001.gif">
<meta property="og:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image009_0000.gif">
<meta property="og:updated_time" content="2019-01-21T13:59:48.415Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="5.2 指令系统">
<meta name="twitter:description" content="5.2.1 数据传送指令数据传送指令又分为：传送指令、交换指令、地址传送指令、堆栈操作指令、转换指令和I/O指令等。 除了标志位操作指令SAHF和POPF指令外，本类的其它指令都不影响标志位。 1、传送指令MOV(Move Instruction)传送指令是使用最频繁的指令，它相对于高级语言里的赋值语句。指令的格式如下： 1MOV   Reg/Mem, Reg/Mem/Imm 其中：Reg—Reg">
<meta name="twitter:image" content="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0004.gif">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/limh/',
    scheme: 'Gemini',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="https://tdnr.gitee.io/limh/2015/04/01/asm22/">





  <title>5.2 指令系统 | 土逗牛肉</title>
  








</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans ">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/limh/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">土逗牛肉</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle"></p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/limh/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br>
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/limh/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br>
            
            归档
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/limh/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br>
            
            标签
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/limh/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br>
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/limh/about/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br>
            
            关于
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://tdnr.gitee.io/limh/limh/2015/04/01/asm22/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="土逗牛肉">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/limh/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="土逗牛肉">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">5.2 指令系统</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2015-04-01T20:35:47+08:00">
                2015-04-01
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/limh/categories/汇编教程/" itemprop="url" rel="index">
                    <span itemprop="name">汇编教程</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <h2 id="5-2-1-数据传送指令"><a href="#5-2-1-数据传送指令" class="headerlink" title="5.2.1 数据传送指令"></a>5.2.1 数据传送指令</h2><p>数据传送指令又分为：传送指令、交换指令、地址传送指令、堆栈操作指令、转换指令和I/O指令等。</p>
<p>除了标志位操作指令SAHF和POPF指令外，本类的其它指令都不影响标志位。</p>
<h3 id="1、传送指令MOV-Move-Instruction"><a href="#1、传送指令MOV-Move-Instruction" class="headerlink" title="1、传送指令MOV(Move Instruction)"></a>1、传送指令MOV(Move Instruction)</h3><p>传送指令是使用最频繁的指令，它相对于高级语言里的赋值语句。指令的格式如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">MOV   Reg/Mem, Reg/Mem/Imm</span><br></pre></td></tr></table></figure>
<p>其中：Reg—Register(寄存器)，Mem—Memory(存储器)，Imm—Immediate(立即数)，它们可以是8位、16位或32位(特别指出其位数的除外)。在本网络课件的网页中，都将采用上述缩写，此后不再说明。</p>
<p>指令的功能是把源操作数(第二操作数)的值传给目的操作数(第一操作数)。指令执行后，目的操作数的值被改变，而源操作数的值不变。在存储单元是该指令的一个操作数时，该操作数的寻址方式可以是任意一种存储单元寻址方式。</p>
<p>下面列举几组正确的指令例子：</p>
<h4 id="源操作数是寄存器"><a href="#源操作数是寄存器" class="headerlink" title="源操作数是寄存器"></a>源操作数是寄存器</h4><ul>
<li>MOV  CH, AL</li>
<li>MOV  BP, SP</li>
<li>MOV  ECX, EBX</li>
<li>MOV  DS, AX MOV </li>
<li>[BX], CH MOV  [BX+SI], AX</li>
</ul>
<h4 id="源操作数是存储单元"><a href="#源操作数是存储单元" class="headerlink" title="源操作数是存储单元"></a>源操作数是存储单元</h4><ul>
<li>MOV  AL, [100H]</li>
<li>MOV  BX, ES:[DI]</li>
<li>MOV  EDX, [BX]</li>
<li>MOV  BX, VARW</li>
<li>MOV  AX, [BX+SI]</li>
<li>MOV  CH, [BX+DI+100H]</li>
</ul>
<p>其中：VARW是字类型内存变量(下同)。</p>
<h4 id="源操作数是立即数"><a href="#源操作数是立即数" class="headerlink" title="源操作数是立即数"></a>源操作数是立即数</h4><ul>
<li>MOV  AL, 89H</li>
<li>MOV  BX, -100H</li>
<li>MOV  EDX, 12345678H</li>
<li>MOV  VARW, 200H</li>
<li>MOV  [BX], 2345H</li>
<li>MOV  [BX+DI], 1234H</li>
</ul>
<p>在汇编语言中，主要的数据传送方式如图5.1所示。虽然一条MOV指令能实现其中大多数的数据传送方式，但也存在MOV指令不能实现的传送方式。</p>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0004.gif" alt="图5.1 MOV指令数据传送示意图"></p>
<center><strong>图5.1 MOV指令数据传送示意图</strong></center>

<p>对MOV指令有以下几条具体规定，其中有些规定对其它指令也同样有效。</p>
<ol>
<li>两个操作数的数据类型要相同，要同为8位、16位或32位；如：MOV  BL, AX等是不正确的；</li>
<li>两个操作数不能同时为段寄存器，如：MOV  ES, DS等；</li>
<li>代码段寄存器CS不能为目的操作数，但可作为源操作数，如：指令MOV  CS, AX等不正确，但指令MOV  AX, CS等是正确的；</li>
<li>立即数不能直接传给段寄存器，如：MOV  DS, 100H等；</li>
<li>立即数不能作为目的操作数，如：MOV  100H, AX等；</li>
<li>指令指针IP，不能作为MOV指令的操作数；</li>
<li>两个操作数不能同时为存储单元，如：MOV  VARA, VARB等，其中VARA和VARB是同数据类型的内存变量。</li>
</ol>
<p>对于规定2、4和7，我们可以用通用寄存器作为中转来达到最终目的。表5.1列举一个可行的解决方案，尽供参考。读者可考虑用其它办法来完成同样的功能。</p>
<p><strong>表5.1 MOV指令的变通方法</strong></p>
<table>
<thead>
<tr>
<th>功能描述</th>
<th>不正确的指令</th>
<th>可选的解决方法</th>
</tr>
</thead>
<tbody>
<tr>
<td>把DS的值传送给ES</td>
<td>MOV  ES, DS</td>
<td>MOV  AX, DS <br> MOV  ES, AX</td>
</tr>
<tr>
<td>把100H传给DS</td>
<td>MOV  DS, 100H</td>
<td>MOV  AX, 100H <br>  MOV  DS, AX</td>
</tr>
<tr>
<td>把字变量VARB的值传送给字变量VARA</td>
<td>MOV  VARA, VARB</td>
<td>MOV  AX, VARB <br> MOV  VARA, AX</td>
</tr>
</tbody>
</table>
<p>对于情况1：不同位数数据之间的传送问题，在80386及其以后的CPU中，增加一组新的指令——传送－填充指令，它可把位数少的源操作数传送给位数多的目的操作数，多出的部分按指令的规定进行填充。</p>
<h3 id="2、传送—填充指令-Move-and-Fill-Instruction"><a href="#2、传送—填充指令-Move-and-Fill-Instruction" class="headerlink" title="2、传送—填充指令(Move-and-Fill Instruction)"></a>2、传送—填充指令(Move-and-Fill Instruction)</h3><p>传送—填充指令是把位数短的源操作数传送给位数长的目的操作数。指令格式如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">MOVSX/MOVZX   Reg/Mem, Reg/Mem/Imm　　　　　;80386+</span><br></pre></td></tr></table></figure>
<p>其中：80386+表示80386及其之后的CPU，其它类似符号含义类同，不再说明。</p>
<p>指令的主要功能和限制与MOV指令类似，不同之处是：在传送时，对目的操作数的高位进行填充。根据其填充方式，又分为：符号填充和零填充。</p>
<p>传送—填充指令的功能如图5.2所示。</p>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image001_0023.gif" alt></p>
<center>(a). MOVSX的执行效果</center>

<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0006.gif" alt></p>
<center>(b). MOVZX的执行效果</center>

<center><strong>图5.2 传送—填充指令执行过程示意图</strong></center>

<p><strong>符号填充指令MOVSX(Move with Sign-Extend)</strong></p>
<p>MOVSX的填充方式是：用源操作数的符号位来填充目的操作数的高位数据位。</p>
<p><strong>零填充指令MOVZX(Move with Zero-Extend)</strong></p>
<p>MOVZX的填充方式是：恒用0来填充目的操作数的高位数据位。</p>
<p><strong>例5.1 已知：AL=87H，指令MOVSX  CX, AL，MOVZX  DX, AL执行后，问CX和DX的值是什么？</strong></p>
<p>解：根据传送－填充指令的填充方式可知：</p>
<p>指令MOVSX CX, AL执行后，(CX)=0FF87H，指令MOVZX DX, AL执行后，(DX)=0087H。</p>
<p>从上例可看出，两条指令的源操作数完全一样，但因为它们的填充方式不同，所得到的结果而就不同。</p>
<p>试比较下列指令，分析它们执行结果的相同和不同之处：</p>
<p> MOV　AX, 87H　　　MOVSX　AX, 87H　　　MOVZX　AX, 87H</p>
<h3 id="3、交换指令XCHG-Exchange-Instruction"><a href="#3、交换指令XCHG-Exchange-Instruction" class="headerlink" title="3、交换指令XCHG(Exchange Instruction)"></a>3、交换指令XCHG(Exchange Instruction)</h3><p>交换指令XCHG是两个寄存器，寄存器和内存变量之间内容的交换指令，两个操作数的数据类型要相同。其指令格式如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">XCHG   Reg/Mem, Reg/Mem</span><br></pre></td></tr></table></figure>
<p>该指令的功能和MOV指令不同，后者是一个操作数的内容被修改，而前者是两个操作数都会发生改变。寄存器不能是段寄存器，两个操作数也不能同时为内存变量。</p>
<p>XCHG指令的功能如图5.3所示。</p>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image001_0024.gif" alt="图5.3 XCHG指令的执行功能示意图"></p>
<center><strong>图5.3 XCHG指令的执行功能示意图</strong></center>

<p>例5.2 已知：AX=5678H，BX=1234H，指令XCHG  AX, BX执行后，AX和BX的值是什么？</p>
<p>解：这是两个寄存器内容进行交换，指令执行后，有：(AX)=1234H，(BX)=5678H。</p>
<h3 id="4、取有效地址指令LEA-Load-Effective-Address"><a href="#4、取有效地址指令LEA-Load-Effective-Address" class="headerlink" title="4、取有效地址指令LEA(Load Effective Address)"></a>4、取有效地址指令LEA(Load Effective Address)</h3><p>指令LEA是把一个内存变量的有效地址送给指定的寄存器。其指令格式如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">LEA　Reg, Mem</span><br></pre></td></tr></table></figure>
<p>该指令通常用来对指针或变址寄存器BX、DI或SI等置初值之用。其功能如右图所示。</p>
<p>例如：</p>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0007.gif" alt="图5.4 LEA指令的功能示意图"></p>
<center><strong>图5.4 LEA指令的功能示意图</strong></center>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">…</span><br><span class="line">  BUFFER? DB  100 DUP(?)</span><br><span class="line">  …</span><br><span class="line">  LEA BX, BUFFER　　　　　;把字节变量BUFFER在数据段内的偏移量送给BX</span><br><span class="line">…</span><br></pre></td></tr></table></figure>
<p>问题：指令“LEA  BX BUFFER”和“MOV  BX, OFFSET BUFFER”的执行效果是一样的吗？指令“LEA BX,[BX+200]”和“MOV BX,OFFSET [BX+200]”二者都正确吗？</p>
<h3 id="5、取段寄存器指令-Load-Segment-Instruction"><a href="#5、取段寄存器指令-Load-Segment-Instruction" class="headerlink" title="5、取段寄存器指令(Load Segment Instruction)"></a>5、取段寄存器指令(Load Segment Instruction)</h3><p>该组指令的功能是把内存单元的一个“低字”传送给指令中指定的16位寄存器，把随后的一个“高字”传给相应的段寄存器(DS、ES、FS、GS和SS)。其指令格式如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">LDS/LES/LFS/LGS/LSS　Reg, Mem</span><br></pre></td></tr></table></figure>
<p>指令LDS(Load Data Segment Register)和LES(Load Extra Segment Register)在8086CPU中就存在，而LFS和LGS(Load Extra Segment Register)、LSS(Load Stack Segment Register)是80386及其以后CPU中才有的指令。</p>
<p>若Reg是16位寄存器，那么，Men必须是32位指针；若Reg是32位寄存器，那么，Men必须是48位指针，其低32位给指令中指定的寄存器，高16给指令中的段寄存器。指令的执行结果如图5.5所示。</p>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image001_0025.gif" alt></p>
<center>(a) 32位指针</center>

<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0008.gif" alt></p>
<center>(b) 48位指针</center>

<center><strong>图5.5、LDS指令的执行步骤示意图</strong></center>

<p>例如：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">…</span><br><span class="line"> POINTER　DD　12345678H</span><br><span class="line"> …</span><br><span class="line"> LDS BX, POINTER</span><br><span class="line"> …</span><br></pre></td></tr></table></figure>
<p>指令的执行结果如图5.5所示。各寄存器的内容分别为：(BX)=5678H，(DS)=1234H。</p>
<p>下面控件是学习和掌握MOV、MOVSX/MOVZX、XCHG、LEA、LDS/LES/LFS/LGS/LSS指令的，它可检查用户输入这些指令的合法性，并对合法的指令显示其执行的结果。</p>
<p>注意：如果指令中含有表示内存单元的寻址方式，那么其控件中的”内存单元的类型”即表示该指令中内存单元的数据类型。</p>
<h3 id="6、堆栈操作指令-Stack-Operation-Instruction"><a href="#6、堆栈操作指令-Stack-Operation-Instruction" class="headerlink" title="6、堆栈操作指令(Stack Operation Instruction)"></a>6、堆栈操作指令(Stack Operation Instruction)</h3><p>堆栈是一个重要的数据结构，它具有“先进后出”的特点，通常用来保存程序的返回地址。它主要有两大类操作：进栈操作和出栈操作。</p>
<h4 id="1-、进栈操作"><a href="#1-、进栈操作" class="headerlink" title="1)、进栈操作"></a>1)、进栈操作</h4><ul>
<li>PUSH(Push Word or Doubleword onto Stack)</li>
</ul>
<p>指令格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">PUSH　Reg/Mem </span><br><span class="line">    PUSH　Imm　　　　　　　　　　;80286+</span><br></pre></td></tr></table></figure>
<p>一个字进栈，系统自动完成两步操作：SP←SP-2，(SP)←操作数；</p>
<p> 一个双字进栈，系统自动完成两步操作：ESP←ESP-4，(ESP)←操作数。</p>
<ul>
<li>PUSHA(Push All General Registers)</li>
</ul>
<p>指令格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">PUSHA　　　　　　　;80286+</span><br></pre></td></tr></table></figure>
<p>其功能是依次把寄存器AX、CX、DX、BX、SP、BP、SI和DI等压栈。</p>
<ul>
<li>PUSHAD(Push All 32-bit General Registers)</li>
</ul>
<p>指令格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">PUSHAD　　　　　　　;80386+</span><br></pre></td></tr></table></figure>
<p>其功能是把寄存器EAX、ECX、EDX、EBX、ESP、EBP、ESI和EDI等压栈。</p>
<h4 id="2-、出栈操作"><a href="#2-、出栈操作" class="headerlink" title="2)、出栈操作"></a>2)、出栈操作</h4><ul>
<li>POP(Pop Word or Doubleword off Stack)</li>
</ul>
<p>指令格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">POP　Reg/Mem</span><br></pre></td></tr></table></figure>
<p>弹出一个字，系统自动完成两步操作：操作数←(SP)，SP←SP-2；</p>
<p>弹出一个双字，系统自动完成两步操作：操作数←(ESP)，ESP←ESP-4。</p>
<ul>
<li>POPA(Pop All General Registers)</li>
</ul>
<p>指令格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">POPA　　　　　　　;80286+</span><br></pre></td></tr></table></figure>
<p>其功能是依次把寄存器DI、SI、BP、SP、BX、DX、CX和AX等弹出栈。其实，程序员不用记住它们的具体顺序，只要与指令PUSHA对称使用就可以了。</p>
<ul>
<li>POPAD(Pop All 32-bit General Registers)</li>
</ul>
<p>指令格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">POPAD　　　　　　;80386+</span><br></pre></td></tr></table></figure>
<p>其功能是依次把寄存器EDI、ESI、EBP、ESP、EBX、EDX、ECX和EAX等弹出栈，它与PUSHAD对称使用即可。</p>
<h3 id="7、转换指令XLAT-Translate-Instruction"><a href="#7、转换指令XLAT-Translate-Instruction" class="headerlink" title="7、转换指令XLAT(Translate Instruction)"></a>7、转换指令XLAT(Translate Instruction)</h3><p>转换指令有两个隐含操作数BX和AL。</p>
<p>指令格式如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">XLAT/XLATB</span><br></pre></td></tr></table></figure>
<p>其功能是把BX的值作为内存字节数组首地址、下标为AL的数组元素的值传送给AL。其功能描述的表达式是：AL←BX[AL]，其功能示意图如图5.6所示。</p>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image001_0032.gif" alt="图5.6 XLAT/XLATB指令的功能示意图"></p>
<center><strong>图5.6 XLAT/XLATB指令的功能示意图</strong></center>

<h3 id="8、I-O指令"><a href="#8、I-O指令" class="headerlink" title="8、I/O指令"></a>8、I/O指令</h3><p>有关I/O指令将在第8.1.2节——I/O指令——中介绍，在此从略。</p>
<h2 id="5-2-2-标志位操作指令"><a href="#5-2-2-标志位操作指令" class="headerlink" title="5.2.2 标志位操作指令"></a>5.2.2 标志位操作指令</h2><p>标志位操作指令是一组对标志位置位复位保存和恢复等操作的指令。</p>
<h3 id="1-进位CF操作指令"><a href="#1-进位CF操作指令" class="headerlink" title="1.进位CF操作指令"></a>1.进位CF操作指令</h3><p>清进位指令CLC(Clear Carry Flag)：CF←0</p>
<p>置进位指令STC(Set Carry Flag)：CF←1</p>
<p>进位取反指令CMC(Complement Carry Flag)：CF←not CF</p>
<h3 id="2-方向位DF操作指令"><a href="#2-方向位DF操作指令" class="headerlink" title="2.方向位DF操作指令"></a>2.方向位DF操作指令</h3><p>清方向位指令CLD(Clear Direction Flag)：DF←0</p>
<p>置方向位指令STD(Set Direction Flag)：DF←1</p>
<h3 id="3-中断允许位IF操作指令"><a href="#3-中断允许位IF操作指令" class="headerlink" title="3.中断允许位IF操作指令"></a>3.中断允许位IF操作指令</h3><p>清中断允许位指令CLI(Clear Interrupt Flag)：IF←0</p>
<p>其功能是不允许可屏蔽的外部中断来中断其后程序段的执行。</p>
<p>置中断允许位指令STI(Set Interrupt Flag)：IF←1</p>
<p>其功能是恢复可屏蔽的外部中断的中断响应功能，通常是与CLI成对使用的。</p>
<h3 id="4-取标志位操作指令"><a href="#4-取标志位操作指令" class="headerlink" title="4.取标志位操作指令"></a>4.取标志位操作指令</h3><p>LAHF(Load AH from Flags)：AH←Flags的低8位</p>
<p>SAHF(Store AH in Flags)：Flags的低8位←AH</p>
<h3 id="5-标志位堆栈操作指令"><a href="#5-标志位堆栈操作指令" class="headerlink" title="5.标志位堆栈操作指令"></a>5.标志位堆栈操作指令</h3><p>PUSHF/PUSHFD(Push Flags onto Stack)：把16位/32位标志寄存器进栈；</p>
<p>POPF/POPFD(Pop Flags off Stack)：把16位/32位标志寄存器出栈；</p>
<h3 id="6-逻辑操作指令的小结"><a href="#6-逻辑操作指令的小结" class="headerlink" title="6.逻辑操作指令的小结"></a>6.逻辑操作指令的小结</h3><p>下面是学习标志位指令的控件，浏览者可以运用此类指令，观看标志寄存器的相应变化。</p>
<h2 id="5-2-3-算术运算指令"><a href="#5-2-3-算术运算指令" class="headerlink" title="5.2.3 算术运算指令"></a>5.2.3 算术运算指令</h2><p>算术运算指令是反映CPU计算能力的一组指令，也是编程时经常使用的一组指令。它包括：加、减、乘、除及其相关的辅助指令。</p>
<p>该组指令的操作数可以是8位、16位和32位(80386+)。当存储单元是该类指令的操作数时，该操作数的寻址方式可以是任意一种存储单元寻址方式。</p>
<h3 id="1、加法指令"><a href="#1、加法指令" class="headerlink" title="1、加法指令"></a>1、加法指令</h3><ul>
<li>加法指令ADD(ADD Binary Numbers Instruction)</li>
</ul>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ADD  Reg/Mem, Reg/Mem/Imm</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：AF、CF、OF、PF、SF和ZF</p>
<p>指令的功能是把源操作数的值加到目的操作数中。</p>
<ul>
<li>带进位加指令ADC(ADD With Carry Instruction)</li>
</ul>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ADC  Reg/Mem, Reg/Mem/Imm</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：AF、CF、OF、PF、SF和ZF</p>
<p>指令的功能是把源操作数和进位标志位CF的值(0/1)一起加到目的操作数中。</p>
<ul>
<li>加1指令INC(Increment by 1 Instruction)</li>
</ul>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">INC  Reg/Mem</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：AF、OF、PF、SF和ZF，不影响CF</p>
<p>指令的功能是把操作数的值加1。</p>
<ul>
<li>交换加指令XADD(Exchange and Add)</li>
</ul>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">XADD  Reg/Mem, Reg　　　　　　;80486+</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：AF、CF、OF、PF、SF和ZF</p>
<p>指令的功能是先交换两个操作数的值，再进行算术“加”法操作。</p>
<p><strong>例5.3 已知有二个32位数d1和d2(用数据类型DD说明)，编写程序片段把d2的值加到d1中。</strong></p>
<p>解：32位数d1和d2在内存中如下所示。</p>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0009.gif" alt></p>
<p><strong>方法1：用16位寄存器编写程序</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">MOV  AX, word ptr d1            ;由于d1是双字类型，必须使用强制类型说明符。以下同。</span><br><span class="line">MOV  DX, word ptr d1+2        ;(DX,AX)构成一个32位数据 </span><br><span class="line">ADD  AX, word ptr d2            ;低字相加</span><br><span class="line">ADC  DX, word ptr d2+2        ;高字相加。在低字相加时，有可能会产生“进位”</span><br><span class="line">MOV  word ptr d1, AX             ;低字送给d1的低字</span><br><span class="line">MOV  word ptr d1+2, DX        ;高字送给d1的高字</span><br></pre></td></tr></table></figure>
<p><strong>方法2：用32位寄存器编写程序</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">MOV  EAX, d1 </span><br><span class="line"> ADD  EAX, d2 </span><br><span class="line"> MOV  d1, EAX</span><br></pre></td></tr></table></figure>
<p>从上面两段程序不难看出：用32位寄存器来处理32位数据显得简单、明了，而16位微机虽然也能处理32位数据，但做起来就要复杂一些。</p>
<p>下面是学习和掌握加法类指令的控件，可模拟执行ADD、ADC、INC、XADD、CLC、STC和CMC等指令。用鼠标左键单击寄存器列表框中指定的寄存器，则可修改其值。后面其它控件的有关操作与此相一致，不再说明。</p>
<h3 id="2、减法指令"><a href="#2、减法指令" class="headerlink" title="2、减法指令"></a>2、减法指令</h3><ul>
<li>减法指令SUB(Subtract Binary Values Instruction)</li>
</ul>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">SUB  Reg/Mem, Reg/Mem/Imm</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：AF、CF、OF、PF、SF和ZF</p>
<p>指令的功能是从目的操作数中减去源操作数。</p>
<ul>
<li>带借位减SBB(Subtract with Borrow Instruction)</li>
</ul>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">SBB  Reg/Mem, Reg/Mem/Imm</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：AF、CF、OF、PF、SF和ZF</p>
<p>指令的功能是把源操作数和标志位CF的值从目的操作数中一起减去。</p>
<ul>
<li>减1指令DEC(Decrement by 1 Instruction)</li>
</ul>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">DEC  Reg/Mem</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：AF、OF、PF、SF和ZF，不影响CF</p>
<p>指令的功能是把操作数的值减去1。</p>
<ul>
<li>求补指令NEG(Negate Instruction)</li>
</ul>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">NEG  Reg/Mem</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：AF、CF、OF、PF、SF和ZF</p>
<p>指令的功能：操作数＝0－操作数，即改变操作数的正负号。</p>
<p><strong>例5.4 已知有二个32位数d1和d2，编写程序片段从d1中减去d2的值。</strong></p>
<p>解：</p>
<p><strong>方法1：用16位寄存器编写程序</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">MOV AX, word ptr d1 ;取低字</span><br><span class="line"></span><br><span class="line">MOV DX, word ptr d1+2 ;取高字，(DX,AX)构成一个32位数据 </span><br><span class="line"></span><br><span class="line">SUB AX, word ptr d2 ;低字相减</span><br><span class="line"></span><br><span class="line">SBB DX, word ptr d2+2 ;高字相减。在低字相减时，有可能会产生“借位”</span><br><span class="line"></span><br><span class="line">MOV word ptr d1, AX ;低字送给d1的低字</span><br><span class="line"></span><br><span class="line">MOV word ptr d1+2, DX ;高字送给d1的高字</span><br></pre></td></tr></table></figure>
<p><strong>方法2：用32位寄存器编写程序</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">MOV       EAX, d1</span><br><span class="line"></span><br><span class="line">SUB       EAX, d2</span><br><span class="line"></span><br><span class="line">MOV       d1, EAX</span><br></pre></td></tr></table></figure>
<p>下面是学习和掌握减法类指令的控件，可模拟执行SUB、SBB、DEC、NEG、CLC、STC和CMC等指令。</p>
<h3 id="3、乘法指令"><a href="#3、乘法指令" class="headerlink" title="3、乘法指令"></a>3、乘法指令</h3><p>计算机的乘法指令分为无符号乘法指令和有符号乘法指令，它们的唯一区别就在于：数据的最高位是作为“数值”参与运算，还是作为“符号位”参与运算。</p>
<p>乘法指令的被乘数都是隐含操作数，乘数在指令中显式地写出来。CPU会根据乘数是8位、16位，还是32位操作数，来自动选用被乘数：AL、AX或EAX。</p>
<p>指令的功能是把显式操作数和隐含操作数相乘，并把乘积存入相应的寄存器中。</p>
<ul>
<li>无符号数乘法指令MUL(Unsigned Multiply Instruction)</li>
</ul>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">MUL  Reg/Mem</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：CF和OF(AF、PF、SF和ZF无定义)</p>
<p>指令的功能是把显式操作数和隐含操作数(都作为无符号数)相乘，所得的乘积按表5.2的对应关系存放。</p>
<p><strong>表5.2 乘法指令中乘数、被乘数和乘积的对应关系</strong></p>
<table>
<thead>
<tr>
<th>乘数位数</th>
<th>隐含的被乘数</th>
<th>乘积的存放位置</th>
<th>举例</th>
</tr>
</thead>
<tbody>
<tr>
<td>8位</td>
<td>AL</td>
<td>AX</td>
<td>MUL  BL</td>
</tr>
<tr>
<td>16位</td>
<td>AX</td>
<td>DX-AX</td>
<td>MUL  BX</td>
</tr>
<tr>
<td>32位</td>
<td>EAX</td>
<td>EDX-EAX</td>
<td>MUL  ECX</td>
</tr>
</tbody>
</table>
<ul>
<li>有符号数乘法指令IMUL(Signed Integer Multiply Instruction)</li>
</ul>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">IMUL Reg/Mem</span><br><span class="line">IMUL Reg, Imm ;80286+</span><br><span class="line">IMUL Reg, Reg, Imm ;80286+</span><br><span class="line">IMUL Reg, Reg/Mem ;80386+</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：CF和OF(AF、PF、SF和ZF无定义)</p>
<ol>
<li>指令格式1——该指令的功能是把显式操作数和隐含操作数相乘，所得的乘积按表5.2的对应关系存放。</li>
<li>指令格式2——其寄存器必须是16位/32位通用寄存器，其计算方式为：<br>Reg ← Reg × Imm</li>
<li>指令格式3——其寄存器只能是16位通用寄存器，其计算方式为：<br>Reg1 ← Reg2×Imm  或  Reg1 ← Mem×Imm</li>
<li>指令格式4——其寄存器必须是16位/32位通用寄存器，其计算方式为：<br>Reg1 ← Reg1×Reg2  或  Reg1 ← Reg1×Mem</li>
</ol>
<p>在指令格式2~4中，各操作数的位数要一致。如果乘积超过目标寄存器所能存储的范围，则系统将置溢出标志OF为1。</p>
<p>下面是学习和掌握乘法类指令的控件，可模拟执行MUL和IMUL等指令。</p>
<h3 id="4、除法指令"><a href="#4、除法指令" class="headerlink" title="4、除法指令"></a>4、除法指令</h3><p>除法指令的被除数是隐含操作数，除数在指令中显式地写出来。CPU会根据除数是8位、16位，还是32位，来自动选用被除数AX、DX-AX，还是EDX-EAX。</p>
<p>除法指令功能是用显式操作数去除隐含操作数，可得到商和余数。当除数为0，或商超出数据类型所能表示的范围时，系统会自动产生0号中断。</p>
<ul>
<li>无符号数除法指令DIV(Unsigned Divide Instruction)</li>
</ul>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">DIV  Reg/Mem</span><br></pre></td></tr></table></figure>
<p>指令的功能是用显式操作数去除隐含操作数(都作为无符号数)，所得商和余数按表5.3的对应关系存放。指令对标志位的影响无定义。</p>
<ul>
<li>有符号数除法指令IDIV(Signed Integer Divide Instruction)</li>
</ul>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">IDIV  Reg/Mem</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：AF、CF、OF、PF、SF和ZF</p>
<p>指令的功能是用显式操作数去除隐含操作数(都作为有符号数)，所得商和余数的对应关系见表5.3。</p>
<p><strong>表5.3 除法指令除数、被除数、商和余数的对应关系</strong></p>
<table>
<thead>
<tr>
<th>除数位数</th>
<th>隐含的被除数</th>
<th>商</th>
<th>余数</th>
<th>举例</th>
</tr>
</thead>
<tbody>
<tr>
<td>8位</td>
<td>AX</td>
<td>AL</td>
<td>AH</td>
<td>DIV BH</td>
</tr>
<tr>
<td>16位</td>
<td>DX-AX</td>
<td>AX</td>
<td>DX</td>
<td>DIV  BX</td>
</tr>
<tr>
<td>32位</td>
<td>EDX-EAX</td>
<td>EAX</td>
<td>EDX</td>
<td>DIV  ECX</td>
</tr>
</tbody>
</table>
<h3 id="5、类型转换指令"><a href="#5、类型转换指令" class="headerlink" title="5、类型转换指令"></a>5、类型转换指令</h3><p>在作有符号除法时，有时需要把短位数的被除数转换成位数更长的数据类型。比如，要用BL中的数据去除AL，但根据除法指令的规定：除数是8位，则被除数必须是AX，于是就涉及到AH的取值问题。</p>
<p>为了方便说明，假设：(AH)=1H，(AL)=90H=-112D，(BL)=10H。</p>
<ol>
<li>在作除法运算前，必须处理AH的原有内容</li>
</ol>
<p>假设在作除法时，不管AH中的值，这时，(AH、AL)/BL的商是19H，但我们知道：AL/BL的商应是-7，这就导致：计算结果不是所预期的结果，所以，在作除法运算前，程序员必须要处理AH中的值。</p>
<ol start="2">
<li>作无符号数除法时</li>
</ol>
<p>可强置AH的值为0，于是，可得到正确的结果。</p>
<ol start="3">
<li>作有符号数除法时</li>
</ol>
<p>如果强置AH为0，则AX=0090H，这时，AX/BL的商为9，显然结果也不正确。</p>
<p>如果把AL的符号位1，扩展到AH中，得：AX=0FF90H=-112D，这时，AX/BL的商就是我们所要的正确结果。</p>
<p>综上所述，因为在进行有符号数除法时存在隐含操作数数据类型转换的问题，所以，系统提供了四条数据类型转换指令：CBW、CWD、CWDE和CDQ。</p>
<ul>
<li>字节转换为字指令CBW(Convent Byte to Word)</li>
</ul>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">CBW</span><br></pre></td></tr></table></figure>
<p>该指令的隐含操作数为AH和AL。其功能是用AL的符号位去填充AH，即：当AL为正数，则AH=0，否则，AH=0FFH。</p>
<p>指令的执行不影响任何标志位。</p>
<ul>
<li>字转换为双字指令CWD(Convent Word to Doubleword)</li>
</ul>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">CWD</span><br></pre></td></tr></table></figure>
<p>该指令的隐含操作数为DX和AX，其功能是用AX的符号位去填充DX。指令的执行不影响任何标志位。</p>
<ul>
<li>字转换为扩展的双字指令CWDE(Convent Word to Extended Doubleword)</li>
</ul>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">CWDE　　　　　　　　;80386+</span><br></pre></td></tr></table></figure>
<p>该指令的隐含操作数为DX和AX，其功能是用AX的符号位填充EAX的高字位。指令的执行不影响任何标志位。</p>
<ul>
<li>双字转换为四字指令CDQ(Convent Doubleword to Quadword)</li>
</ul>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">CDQ　　　　　　　　　;80386+</span><br></pre></td></tr></table></figure>
<p>该指令的隐含操作数为EDX和EAX，指令的功能是用EAX的符号位填充EDX。指令的执行不影响任何标志位。</p>
<p>下面是学习和掌握除法类指令的控件，可模拟执行DIV、IDIV、CBW、CWD、CWDE和CDQ等指令。</p>
<p><strong>例5.5 编写程序段，完成下面计算公式，并把所得的商和余数分别存入X和Y中(其中：A，B，C，X和Y都是有符号的字变量)。</strong></p>
<p>(C - 120 + A*B) / C</p>
<p>解：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">…</span><br><span class="line"> A   DW  ?</span><br><span class="line"> B   DW  ?</span><br><span class="line"> C   DW  ?</span><br><span class="line"> X   DW  ?</span><br><span class="line"> Y   DW  ?</span><br><span class="line"> …</span><br><span class="line"> MOV   AX, C</span><br><span class="line"> SUB AX, 120D    ;书写指令“ADD AX, -120D”也可以</span><br><span class="line"> CWD</span><br><span class="line"> MOV   CX, DX</span><br><span class="line"> MOV   BX, AX  ;(CX,  BX)←(DX, AX)，调度寄存器，为作乘法准备必要的寄存器</span><br><span class="line"> MOV   AX, A</span><br><span class="line"> IMUL   B   ;(DX,  AX)←A*B</span><br><span class="line"> ADD    AX, BX  ;计算32位二进制之和，为作除法作准备</span><br><span class="line"> ADC    DX, CX</span><br><span class="line"> IDIV    C   ;AX是商，DX是余数</span><br><span class="line"> MOV   X, AX   ;分别保存商和余数到指定的字变量单元里</span><br><span class="line"> MOV   Y, DX</span><br><span class="line"> …</span><br></pre></td></tr></table></figure></p>
<h2 id="5-2-4-逻辑运算指令"><a href="#5-2-4-逻辑运算指令" class="headerlink" title="5.2.4 逻辑运算指令"></a>5.2.4 逻辑运算指令</h2><p>逻辑运算指令是另一组重要的指令，它包括：逻辑与(AND)、逻辑或(OR)、逻辑非(NOT)和异或指令(XOR)，逻辑运算指令也是经常使用的指令。</p>
<h3 id="1、逻辑与操作指令AND-Logical-AND-Instruction"><a href="#1、逻辑与操作指令AND-Logical-AND-Instruction" class="headerlink" title="1、逻辑与操作指令AND(Logical AND Instruction)"></a>1、逻辑与操作指令AND(Logical AND Instruction)</h3><p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">AND　Reg/Mem,  Reg/Mem/Imm</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：CF(0)、OF(0)、PF、SF和ZF(AF无定义)</p>
<p>指令的功能是把源操作数中的每位二进制与目的操作数中的相应二进制进行逻辑“与操作”，操作结果存入目标操作数中。</p>
<p><strong>例5.6 已知(BH)=67H，要求把其的第0、1和5位置为0。</strong></p>
<p>解：可以构造一个立即数，其第0、1和5位的值为0，其它位的值为1，该立即数即为：0DCH或11011100B，然后用指令”AND BH, 0DCH”来实现此功能。</p>
<p>其计算过程如下图所示。</p>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image001_0060.gif" alt></p>
<h3 id="2、逻辑或操作指令OR-Logical-OR-Instruction"><a href="#2、逻辑或操作指令OR-Logical-OR-Instruction" class="headerlink" title="2、逻辑或操作指令OR(Logical OR Instruction)"></a>2、逻辑或操作指令OR(Logical OR Instruction)</h3><p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">OR　Reg/Mem,  Reg/Mem/Imm</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：CF(0)、OF(0)、PF、SF和ZF(AF无定义)</p>
<p>指令的功能是把源操作数中的每位二进制与目的操作数中的相应二进制进行逻辑”或操作”，操作结果存入目标操作数中。</p>
<p><strong>例5.7 已知(BL)=46H，要求把其的第1、3、4和6位置为1。</strong></p>
<p>解：构造一个立即数，使其第1、3、4和6位的值为1，其它位的值为0，该立即数即为：5AH或01011010B，然后用指令”OR BL, 5AH”来实现此功能。</p>
<p>其计算过程如下图所示。</p>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0010.gif" alt></p>
<h3 id="3、逻辑非操作指令NOT-Logical-NOT-Instruction"><a href="#3、逻辑非操作指令NOT-Logical-NOT-Instruction" class="headerlink" title="3、逻辑非操作指令NOT(Logical NOT Instruction)"></a>3、逻辑非操作指令NOT(Logical NOT Instruction)</h3><p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">NOT　Reg/Mem</span><br></pre></td></tr></table></figure>
<p>其功能是把操作数中的每位变反，即：1←0，0←1。指令的执行不影响任何标志位。</p>
<p><strong>例5.8 已知(AL)=46H，执行指令“NOT　AL”后，AL的值是什么？</strong></p>
<p>解：执行该指令后，(AL)=0B9H。其计算过程如下所示。</p>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image001_0061.gif" alt></p>
<h3 id="4、逻辑异或操作指令XOR-Exclusive-OR-Instruction"><a href="#4、逻辑异或操作指令XOR-Exclusive-OR-Instruction" class="headerlink" title="4、逻辑异或操作指令XOR(Exclusive OR Instruction)"></a>4、逻辑异或操作指令XOR(Exclusive OR Instruction)</h3><p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">XOR　Reg/Mem,  Reg/Mem/Imm</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：CF(0)、OF(0)、PF、SF和ZF(AF无定义)</p>
<p>指令的功能是把源操作数中的每位二进制与目的操作数中的相应二进制进行逻辑”异或操作”，操作结果存入目标操作数中。</p>
<p><strong>例5.9 已知(AH)=46H，要求把其的第0、2、5和7位的二进制值变反。</strong></p>
<p>解：构造一个立即数，使其第0、2、5和7位的值为1，其它位的值为0，该立即数即为：0A5H或10100101B，然后再用指令”XOR  AH, 0A5H”来实现此功能。</p>
<p>其计算过程如下图所示。</p>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0011.gif" alt></p>
<h3 id="5、逻辑操作指令的小结"><a href="#5、逻辑操作指令的小结" class="headerlink" title="5、逻辑操作指令的小结"></a>5、逻辑操作指令的小结</h3><p>下面是学习和掌握逻辑类指令的控件，可模拟执行AND、OR、NOT和XOR等指令。</p>
<h2 id="5-2-5-移位操作指令"><a href="#5-2-5-移位操作指令" class="headerlink" title="5.2.5 移位操作指令"></a>5.2.5 移位操作指令</h2><p>移位操作指令是一组经常使用的指令，它包括算术移位、逻辑移位、双精度移位、循环移位和带进位的循环移位等五大类。</p>
<p>移位指令都有指定移动二进制位数的操作数，该操作数可以是立即数或CL的值。在8086中，该立即数只能为1，但在其后的CPU中，该立即数可以是1··31之内的数。</p>
<h3 id="1、算术移位指令"><a href="#1、算术移位指令" class="headerlink" title="1、算术移位指令"></a>1、算术移位指令</h3><p>算术移位指令有：算术左移SAL(Shift Algebraic Left)和算术右移SAR(Shift Algebraic Right)。</p>
<p>它们的指令格式如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">SAL/SAR　Reg/Mem,  CL/Imm</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：CF、OF、PF、SF和ZF(AF无定义)。</p>
<p>算术移位指令的功能描述如下，具体功能下图(a)、(b)所示。</p>
<p>算术左移SAL把目的操作数的低位向高位移，空出的低位补0；</p>
<p>算术右移SAR把目的操作数的高位向低位移，空出的高位用最高位(符号位)填补。</p>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0012.gif" alt="(a)、SAL"></p>
<center><strong>(a)、SAL</strong></center>

<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image003_0004.gif" alt="(b)、SAR"></p>
<center><strong>(b)、SAR</strong></center>

<p><strong>例5.10 已知(AH)=12H，(BL)=0A9H，试给出分别用算术左移和右移指令移动1位后，寄存器AH和BL的内容。</strong></p>
<p>解：用算术左移和右移指令移动1位后，寄存器AH和BL的结果如下表所示。</p>
<table>
<thead>
<tr>
<th>操作数的初值</th>
<th>执行的指令</th>
<th>执行后操作数的内容</th>
</tr>
</thead>
<tbody>
<tr>
<td>(AH)=12H</td>
<td>SAL  AH, 1</td>
<td>(AH)=24H</td>
</tr>
<tr>
<td>(BL)=0A9H</td>
<td>SAL  BL, 1</td>
<td>(BL)=52H</td>
</tr>
<tr>
<td>(AH)=12H</td>
<td>SAR  AH, 1</td>
<td>(AH)=09H</td>
</tr>
<tr>
<td>(BL)=0A9H</td>
<td>SAR  BL, 1</td>
<td>(BL)=0D4H</td>
</tr>
</tbody>
</table>
<p>下面是学习和理解算术移位指令的控件。它简单、直观地表达了该移位指令的功能，通过它，学习者可准确地掌握计算机系统中该移位指令的含义。</p>
<p>在该控件中，操作者可随机生成第一操作数，也可自行输入之。为了便于比较，在执行指令前，把原操作数的内容存入“操作前的数据”中。</p>
<h3 id="2、逻辑移位指令"><a href="#2、逻辑移位指令" class="headerlink" title="2、逻辑移位指令"></a>2、逻辑移位指令</h3><p>此组指令有：逻辑左移SHL(Shift Logical Left)和逻辑右移SHR(Shift Logical Right)。</p>
<p>它们的指令格式如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">SHL/SHR　Reg/Mem,  CL/Imm</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：CF、OF、PF、SF和ZF(AF无定义)。</p>
<p>逻辑左移/右移指令只有它们的移位方向不同，移位后空出的位都补0。它们的具体功能下图所示。</p>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image001_0064.gif" alt="(a)、SHL"></p>
<center><strong>(a)、SAL</strong></center>

<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0013.gif" alt="(b)、SHR"></p>
<center><strong>(b)、SAR</strong></center>

<p><strong>例5.11 已知(AH)=12H，(BL)=0A9H，试给出分别用逻辑左移和右移指令移动1位后，寄存器AH和BL的内容。</strong></p>
<p>解：用算术左移和右移指令移动1位后，寄存器AH和BL的结果如下表所示。</p>
<table>
<thead>
<tr>
<th>操作数的初值</th>
<th>执行的指令</th>
<th>执行后操作数的内容</th>
</tr>
</thead>
<tbody>
<tr>
<td>(AH)=12H</td>
<td>SHL  AH, 1</td>
<td>(AH)=24H</td>
</tr>
<tr>
<td>(BL)=0A9H</td>
<td>SHL  BL, 1</td>
<td>(BL)=52H</td>
</tr>
<tr>
<td>(AH)=12H</td>
<td>SHR  AH, 1</td>
<td>(AH)=09H</td>
</tr>
<tr>
<td>(BL)=0A9H</td>
<td>SHR  BL, 1</td>
<td>(BL)=54H</td>
</tr>
</tbody>
</table>
<p>学习和理解逻辑移位指令的控件。</p>
<h3 id="3、双精度移位指令"><a href="#3、双精度移位指令" class="headerlink" title="3、双精度移位指令"></a>3、双精度移位指令</h3><p>此组指令有：双精度左移SHLD(Shift Left Double)和双精度右移SHRD(Shift Right Double)。它们都是具有三个操作数的指令，其指令的格式如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">SHLD/SHRD   Reg/Mem, Reg, CL/Imm　　　　;80386+</span><br></pre></td></tr></table></figure>
<p>其中：第一操作数是一个16位/32位的寄存器或存储单元；第二操作数(与前者具有相同位数)一定是寄存器；第三操作数是移动的位数，它可由CL或一个立即数来确定。</p>
<p>在执行SHLD指令时，第一操作数向左移n位，其“空出”的低位由第二操作数的高n位来填补，但第二操作数自己不移动、不改变。</p>
<p>在执行SHRD指令时，第一操作数向右移n位，其“空出”的高位由第二操作数的低n位来填补，但第二操作数自己也不移动、不改变。</p>
<p>SHLD和SHRD指令的移位功能示意图如图5.8所示。</p>
<p>受影响的标志位：CF、OF、PF、SF和ZF(AF无定义)</p>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image001_0065.gif" alt="(a)、SHLD"></p>
<center>(a)、SHLD</center>

<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0014.gif" alt="(b)、SHRD"></p>
<center>(b)、SHRD</center>

<center><strong>图5.8 双精度移位指令操作示意图</strong></center>

<p>下面是几个双精度移位的例子及其执行结果。</p>
<table>
<thead>
<tr>
<th>双精度移位指令</th>
<th>指令操作数的初值</th>
<th>指令执行后的结果</th>
</tr>
</thead>
<tbody>
<tr>
<td>SHLD</td>
<td>AX, BX, 1</td>
<td>(AX)=1234H，(BX)=8765H</td>
<td>(AX)=2469H</td>
</tr>
<tr>
<td>SHLD</td>
<td>AX, BX, 3</td>
<td>(AX)=1234H，(BX)=8765H</td>
<td>(AX)=91A4H</td>
</tr>
<tr>
<td>SHRD</td>
<td>AX, BX, 2</td>
<td>(AX)=1234H，(BX)=8765H</td>
<td>(AX)=448DH</td>
</tr>
<tr>
<td>SHRD</td>
<td>AX, BX, 4</td>
<td>(AX)=1234H，(BX)=8765H</td>
<td>(AX)=5123H</td>
</tr>
</tbody>
</table>
<p>学习和理解双精度移位指令的控件。</p>
<h3 id="4、循环移位指令"><a href="#4、循环移位指令" class="headerlink" title="4、循环移位指令"></a>4、循环移位指令</h3><p>循环移位指令有：循环左移ROL(Rotate Left)和循环右移ROR(Rotate Right)。</p>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ROL/ROR　Reg/Mem,  CL/Imm</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：CF和OF</p>
<p>循环左移/右移指令只是移位方向不同，它们移出的位不仅要进入CF，而且还要填补空出的位。具体功能如下图所示。</p>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image001_0066.gif" alt="(a)、ROL"></p>
<center>(a)、ROL</center>

<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0015.gif" alt="(b)、ROR"></p>
<center>(b)、ROR</center>

<p>下面是几个循环移位的例子及其执行结果。</p>
<table>
<thead>
<tr>
<th>循环移位指令</th>
<th>指令操作数的初值</th>
<th>指令执行后的结果</th>
</tr>
</thead>
<tbody>
<tr>
<td>ROL  AX, 1</td>
<td>(AX)=6789H</td>
<td>(AX)=0CF12H</td>
</tr>
<tr>
<td>ROL  AX, 3</td>
<td>(AX)=6789H</td>
<td>(AX)=3C4BH</td>
</tr>
<tr>
<td>ROR  AX, 2</td>
<td>(AX)=6789H</td>
<td>(AX)=59E2H</td>
</tr>
<tr>
<td>ROR  AX, 4</td>
<td>(AX)=6789H</td>
<td>(AX)=9678H</td>
</tr>
</tbody>
</table>
<p>学习和理解不带进位的循环移位指令的控件。</p>
<h3 id="5、带进位的循环移位指令"><a href="#5、带进位的循环移位指令" class="headerlink" title="5、带进位的循环移位指令"></a>5、带进位的循环移位指令</h3><p>带进位的循环移位指令有：带进位的循环左移RCL(Rotate Left Through Carry)和带进位的循环右移RCR(Rotate Right)。</p>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">RCL/RCR　Reg/Mem,  CL/Imm</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：CF和OF</p>
<p>带进位的循环左移／右移指令只有移位的方向不同，它们都用原CF的值填补空出的位，移出的位再进入CF。具体功能如下图(a)、(b)所示。</p>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image001_0067.gif" alt="(a)、RC"></p>
<center>(a)、RC</center>

<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0016.gif" alt="(b)、RCR"></p>
<center>(b)、RCR</center>

<p>下面是几个带进位循环移位的例子及其执行结果。</p>
<table>
<thead>
<tr>
<th>双精度移动指令</th>
<th>指令操作数的初值</th>
<th>指令执行后的结果</th>
</tr>
</thead>
<tbody>
<tr>
<td>RCL  AX, 1</td>
<td>CF=0，(AX)=0ABCDH</td>
<td>(AX)=579AH</td>
</tr>
<tr>
<td>RCL  AX, 1</td>
<td>CF=1，(AX)=0ABCDH</td>
<td>(AX)=579BH</td>
</tr>
<tr>
<td>RCR  AX, 2</td>
<td>CF=0，(AX)=0ABCDH</td>
<td>(AX)=AAF3H</td>
</tr>
<tr>
<td>RCR  AX, 2</td>
<td>CF=1，(AX)=0ABCDH</td>
<td>(AX)=EAF3H</td>
</tr>
</tbody>
</table>
<p>例5.12 编写指令序列把由DX和AX组成的32位二进制算术左移、循环左移1位。</p>
<p>解：</p>
<p>(DX,AX)算术左移1位指令序列</p>
<p>SHL  AX, 1</p>
<p>RCL  DX, 1</p>
<p>(DX,AX)循环左移1位指令序列</p>
<p>SHLD  DX, AX, 1</p>
<p>RCL   AX, 1</p>
<h2 id="5-2-6-位操作指令"><a href="#5-2-6-位操作指令" class="headerlink" title="5.2.6 位操作指令"></a>5.2.6 位操作指令</h2><h3 id="1、位扫描指令-Bit-Scan-Instruction"><a href="#1、位扫描指令-Bit-Scan-Instruction" class="headerlink" title="1、位扫描指令(Bit Scan Instruction)"></a>1、位扫描指令(Bit Scan Instruction)</h3><p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">BSF/BSR　Reg,  Reg/Mem　　　　　;80386+</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：ZF</p>
<p>位扫描指令是在第二个操作数中找第一个“1”的位置。如果找到，则该“1”的位置保存在第一操作数中，并置标志位ZF为1，否则，置标志位ZF为0。</p>
<p>根据位扫描的方向不同，指令分二种：正向扫描指令和逆向扫描指令。</p>
<ul>
<li>正向扫描指令BSF(Bit Scan Forward)从右向左扫描，即：从低位向高位扫描；</li>
<li>逆向扫描指令BSR(Bit Scan Reverse)从左向右扫描，即：从高位向低位扫描。</li>
</ul>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0022.gif" alt></p>
<center>(a) BSF</center>

<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image003_0010.gif" alt></p>
<center>(b) BSR n</center>

<center><strong>图5.10 位扫描指令的功能示意图</strong></center>

<p>例如：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"> MOV　AX, 1234H</span><br><span class="line">BSF　CX, AX　　　　　　　;指令执行后，(CX)=2</span><br><span class="line">BSR　CX, AX　　　　　　　;指令执行后，(CX)=12</span><br></pre></td></tr></table></figure>
<h3 id="2、位检测指令-Bit-Test-Instruction"><a href="#2、位检测指令-Bit-Test-Instruction" class="headerlink" title="2、位检测指令(Bit Test Instruction)"></a>2、位检测指令(Bit Test Instruction)</h3><p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">BT/BTC/BTR/BTS　Reg/Mem, Reg/Imm　　　　;80386+</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：CF</p>
<p>位检测指令是把第一个操作数中某一位的值传送给标志位CF，具体的哪一位由指令的第二操作数来确定。</p>
<p>根据指令中对具体位的处理不同，又分一下几种指令：</p>
<ul>
<li><p>BT：把指定的位传送给CF；</p>
</li>
<li><p>BTC：把指定的位传送给CF后，还使该位变反；</p>
</li>
<li><p>BTR：把指定的位传送给CF后，还使该位变为0；</p>
</li>
<li><p>BTS：把指定的位传送给CF后，还使该位变为1；</p>
</li>
</ul>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image004_0001.gif" alt></p>
<center><strong>图5.11 位检测指令的功能示意图</strong></center>

<p>例如：假设(AX)=1234H，分别执行下面指令。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"> BT　　AX, 2　　　　　　;指令执行后，CF=1，(AX)=1234h</span><br><span class="line">BTC　AX, 6　　　　　　 ;指令执行后，CF=0，(AX)=1274h</span><br><span class="line">BTR　AX, 10　　　　　　;指令执行后，CF=0，(AX)=1234h</span><br><span class="line">BTS　AX, 14　　　　　　;指令执行后，CF=0，(AX)=5234h</span><br></pre></td></tr></table></figure>
<h3 id="3、检测位指令TEST-Test-Bits-Instruction"><a href="#3、检测位指令TEST-Test-Bits-Instruction" class="headerlink" title="3、检测位指令TEST(Test Bits Instruction)"></a>3、检测位指令TEST(Test Bits Instruction)</h3><p>检测位指令是把二个操作数进行逻辑“与”操作，并根据运算结果设置相应的标志位，但并不保存该运算结果，所以，不会改变指令中的操作数。在该指令后，通常用JE、JNE、JZ和JNZ等条件转移指令。</p>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">TEST  Reg/Mem, Reg/Mem/Imm</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：CF(0)、OF(0)、PF、SF和ZF(AF无定义)</p>
<p>例如：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">TEST　AX, 1　　　　　　　;测试AX的第0位</span><br><span class="line">TEST　CL, 10101B　　　　;测试CL的第0、2、4位</span><br></pre></td></tr></table></figure>
<p>下面是学习和掌握乘法类指令的控件，可模拟执行BSF、BSR、BT、BTC、BTR、BTS和TEST等指令。</p>
<h2 id="5-2-7-比较运算指令"><a href="#5-2-7-比较运算指令" class="headerlink" title="5.2.7 比较运算指令"></a>5.2.7 比较运算指令</h2><p>在程序中，我们要时常根据某个变量或表达式的取值去执行不同指令，从而使程序表现出有不同的功能。为了配合这样的操作，在CPU的指令系统中提供了各种不同的比较指令。通过这些比较指令的执行来改变有关标志位，为进行条件转移提供依据。</p>
<h3 id="1、比较指令CMP-Compare-Instruction"><a href="#1、比较指令CMP-Compare-Instruction" class="headerlink" title="1、比较指令CMP(Compare Instruction)"></a>1、比较指令CMP(Compare Instruction)</h3><p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">CMP　Reg/Mem,  Reg/Mem/Imm</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：</p>
<p>AF、CF、OF、PF、SF和ZF</p>
<p>指令的功能：用第二个操作数去减第一个操作数，并根据所得的差设置有关标志位，为随后的条件转移指令提供条件。但并不保存该差，所以，不会改变指令中的操作数。</p>
<h3 id="2、比较交换指令-Compare-And-Exchange-Instruction"><a href="#2、比较交换指令-Compare-And-Exchange-Instruction" class="headerlink" title="2、比较交换指令(Compare And Exchange Instruction)"></a>2、比较交换指令(Compare And Exchange Instruction)</h3><p>在数据传送类指令中，我们介绍了交换指令XCHG，它不管二个操作数的值是什么，都无条件地进行交换。而比较交换指令，是先进行比较，再根据比较的结果决定是否进行操作数的交换操作。</p>
<p>比较交换指令的功能：当二个操作数相等时，置标志位ZF为1；否则，把第一操作数的值赋给第二操作数，并置标志位ZF为0。</p>
<p><strong>8位/16位/32位比较交换指令</strong></p>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">CMPXCHG　Reg/Mem,  AL/AX/EAX　　　　;80486+</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：AF、CF、OF、PF、SF和ZF</p>
<p>MASM 6.11中指令的描述与此不同，它没有限定第二操作数的要求。</p>
<p><strong>64位比较交换指令</strong><br>该指令只有一个操作数，第二个操作数EDX:EAX是隐含的。</p>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">CMPXCHG8B　Reg/Mem　　　　　　;Pentium+</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：ZF</p>
<p>例如：假设(AX)=1234H，(BX)=1234H，(CX)=4321H。</p>
<p>CMPXCHG　BX, AX　　　　;指令执行后，ZF=1</p>
<p>CMPXCHG　CX, AX　　　　;指令执行后，ZF=0，(AX)=4321H，CX的值不变</p>
<h3 id="3、字符串比较指令-Compare-String-Instruction"><a href="#3、字符串比较指令-Compare-String-Instruction" class="headerlink" title="3、字符串比较指令(Compare String Instruction)"></a>3、字符串比较指令(Compare String Instruction)</h3><p>参见后面第5.2.11节——字符串操作类指令——的叙述。</p>
<h2 id="5-2-8-循环指令"><a href="#5-2-8-循环指令" class="headerlink" title="5.2.8 循环指令"></a>5.2.8 循环指令</h2><p>循环结构是程序的三大结构之一。为了方便构成循环结构，汇编语言提供了多种循环指令，这些循环指令的循环次数都是保存在计数器CX或ECX中。除了CX或ECX可以决定循环是否结束外，有的循环指令还可由标志位ZF来决定是否结束循环。</p>
<p>在高级语言中，循环计数器可以递增，也可递减，但汇编语言中，CX或ECX只能递减，所以，循环计数器只能从大到小。在程序中，必须先把循环次数赋给循环计数器。</p>
<p>汇编语言的循环指令都是放在循环体的下面，在循环时，首先执行一次循环体，然后把循环计数器CX或ECX减1。当循环终止条件达到满足时，该循环指令下面的指令将是下一条被执行的指令，否则，程序将向上转到循环体的第一条指令。</p>
<p>在循环未终止，而向上转移时，规定：该转移只能是一个短转移，即偏移量不能超过128，也就是说循环体中所有指令码的字节数之和不能超过128。如果循环体过大，可以用后面介绍的“转移指令”来构造循环结构。</p>
<p>循环指令本身的执行不影响任何标志位。</p>
<h3 id="1、循环指令-Loop-Until-Complete"><a href="#1、循环指令-Loop-Until-Complete" class="headerlink" title="1、循环指令(Loop Until Complete)"></a>1、循环指令(Loop Until Complete)</h3><p>循环指令LOOP的一般格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">LOOP　标号</span><br><span class="line"></span><br><span class="line">LOOPW　标号　　　　　 ;CX作为循环计数器，80386+</span><br><span class="line"></span><br><span class="line">LOOPD　标号　　　　　　;ECX作为循环计数器，80386+</span><br></pre></td></tr></table></figure>
<p>循环指令的功能描述：</p>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image005_0000.gif" alt></p>
<center><strong>图5.12 循环指令LOOP的功能示意图</strong></center>

<p>(CX)=(CX)-1或(ECX)=(ECX)-1；</p>
<p>如果(CX)≠0或(ECX)≠0，转向“标号”所指向的指令，否则，终止循环，执行该指令下面的指令。</p>
<p><strong>例5.13 编写一段程序，求1+2+…+1000之和，并把结果存入AX中。</strong></p>
<p>解：</p>
<p>方法1：因为计数器CX只能递减，所以，可把求和式子改变为：1000+999+…+2+1。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">…</span><br><span class="line">XOR AX, AX</span><br><span class="line">MOV CX, 1000D</span><br><span class="line">again: ADD AX,  CX ;计算过程:1000+999+…+2+1</span><br><span class="line">LOOP again</span><br><span class="line">…</span><br></pre></td></tr></table></figure>
<p>方法2：不用循环计数器进行累加，求和式子仍为：1+2+…+999+1000。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">…</span><br><span class="line">XOR AX, AX</span><br><span class="line">MOV CX, 1000D</span><br><span class="line">MOV BX, 1</span><br><span class="line">again: ADD AX,  BX ;计算过程:1+2+…+999+1000</span><br><span class="line">INC BX</span><br><span class="line">LOOP again</span><br><span class="line">…</span><br></pre></td></tr></table></figure>
<p>从程序段的效果来看：方法1要比方法2好。</p>
<h3 id="2、相等或为零循环指令-Loop-While-Equal-or-Loop-While-Zero"><a href="#2、相等或为零循环指令-Loop-While-Equal-or-Loop-While-Zero" class="headerlink" title="2、相等或为零循环指令(Loop While Equal or Loop While Zero)"></a>2、相等或为零循环指令(Loop While Equal or Loop While Zero)</h3><p>相等或为零循环指令的一般格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">LOOPE/LOOPZ　标号</span><br><span class="line"></span><br><span class="line">LOOPEW/LOOPZW　标号　　;CX作为循环计数器，80386+</span><br><span class="line"></span><br><span class="line">LOOPED/LOOPZD　标号　　 ;ECX作为循环计数器，80386+</span><br></pre></td></tr></table></figure>
<p>这是一组有条件循环指令，它们除了要受CX或ECX的影响外，还要受标志位ZF的影响。其具体规定如下：</p>
<p>(1)、(CX)＝(CX)-1或(ECX)＝(ECX)-1；　(不改变任何标志位)</p>
<p>(2)、如果循环计数器≠0且ZF=1，则程序转到循环体的第一条指令，否则，程序将执行该循环指令下面的指令。</p>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image006_0000.gif" alt></p>
<center><strong>图5.13 循环指令LOOPE的功能示意图</strong></center>

<h3 id="3、不等或不为零循环指令-Loop-While-Not-Equal-or-Loop-While-Not-Zero"><a href="#3、不等或不为零循环指令-Loop-While-Not-Equal-or-Loop-While-Not-Zero" class="headerlink" title="3、不等或不为零循环指令(Loop While Not Equal or Loop While Not Zero)"></a>3、不等或不为零循环指令(Loop While Not Equal or Loop While Not Zero)</h3><p>不等或不为零循环指令的一般格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">LOOPNE/LOOPNZ　标号</span><br><span class="line"></span><br><span class="line">LOOPNEW/LOOPNZW　标号　 ;CX作为循环计数器，80386+</span><br><span class="line"></span><br><span class="line">LOOPNED/LOOPNZD　标号　　;ECX作为循环计数器，80386+</span><br></pre></td></tr></table></figure>
<p>这也是一组有条件循环指令，它们与相等或为零循环指令在循环结束条件上有点不同。其具体规定如下：</p>
<p>(1)、(CX)＝(CX)-1或(ECX)＝(ECX)-1；　(不改变任何标志位)</p>
<p>(2)、如果循环计数器≠0且ZF=0，则程序转到循环体的第一条指令，否则，程序将执行该循环指令下面的指令。</p>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image007_0000.gif" alt></p>
<center><strong>图5.14 循环指令LOOPNE的功能示意图</strong></center>

<h3 id="4、循环计数器为零转指令-Jump-if-CX-ECX-is-Zero"><a href="#4、循环计数器为零转指令-Jump-if-CX-ECX-is-Zero" class="headerlink" title="4、循环计数器为零转指令(Jump if CX/ECX is Zero)"></a>4、循环计数器为零转指令(Jump if CX/ECX is Zero)</h3><p>在前面的各类循环指令中，不管循环计数器的初值为何，循环体至少会被执行一次。当循环计数器的初值为0时，通常的理解应是循环体被循环0次，即循环体一次也不被执行。其实不然，循环体不是不被执行，而是会被执行65536次(用CX计数)或4294967296次(几乎是死循环，用ECX计数)。</p>
<p>为了解决指令的执行和常规思维之间差异，指令系统又提供了一条与循环计数器有关的指令——循环计数器为零转指令。该指令一般用于循环的开始处，其指令格式如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">JCXZ　标号　　　;当CX=0时，则程序转移标号处执行</span><br><span class="line">JECXZ　标号　　 ;当ECX=0时，则程序转移标号处执行，80386+</span><br></pre></td></tr></table></figure>
<p><strong>例5.14 编写一段程序，求1+2+…+k(K≥0)之和，并把结果存入AX中。</strong></p>
<p>解：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">…</span><br><span class="line">K   DB　 ?　　　　;变量定义</span><br><span class="line">…</span><br><span class="line">XOR    AX, AX</span><br><span class="line">MOV   CX, K</span><br><span class="line">JCXZ   next</span><br><span class="line">again:   ADD    AX,  CX　　　　;计算过程: K+(K-1)+…+2+1</span><br><span class="line">LOOP   again</span><br><span class="line">next:    …</span><br></pre></td></tr></table></figure>
<h2 id="5-2-9-转移指令"><a href="#5-2-9-转移指令" class="headerlink" title="5.2.9 转移指令"></a>5.2.9 转移指令</h2><p>转移指令是汇编语言程序员经常使用的一组指令。在高级语言中，时常有“尽量不要使用转移语句”的劝告，但如果在汇编语言的程序中也尽量不用转移语句，那么该程序要么无法编写，要么没有多少功能，所以，在汇编语言中，不但要使用转移指令，而且还要灵活运用，因为指令系统中有大量的转移指令。</p>
<p>转移指令分无条件转移指令和有条件转移指令两大类。</p>
<h3 id="1、无条件转移指令-Transfer-Unconditionally"><a href="#1、无条件转移指令-Transfer-Unconditionally" class="headerlink" title="1、无条件转移指令(Transfer Unconditionally)"></a>1、无条件转移指令(Transfer Unconditionally)</h3><p>无条件转移指令包括：JMP、子程序的调用和返回指令、中断的调用和返回指令等。</p>
<p>下面只介绍无条件转移指令JMP(Unconditional Jump)。</p>
<p>JMP指令的一般形式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">JMP  标号/Reg/Mem</span><br></pre></td></tr></table></figure>
<p>JMP指令是从程序当前执行的地方无条件转移到另一个地方执行。这种转移可以是一个短(short)转移(偏移量在[-128, 127]范围内)，近(near)转移(偏移量在[-32K, 32K]范围内)或远(far)转移(在不同的代码段之间转移)。</p>
<p>短和近转移是段内转移，JMP指令只把目标指令位置的偏移量赋值指令指针寄存器IP，从而实现转移功能。但远转移是段间转移，JMP指令不仅会改变指令指针寄存器IP的值，而且还会改变代码段寄存器CS的值。</p>
<p>该转移指令的执行不影响任何标志位。</p>
<p>例如：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">…</span><br><span class="line">next1:  …</span><br><span class="line">JMP next1   ;向前转移，偏移量之差为负数</span><br><span class="line">…</span><br><span class="line">JMP next2   ;向后转移，偏移量之差为正数</span><br><span class="line">…</span><br><span class="line">next2:  …</span><br></pre></td></tr></table></figure>
<p>在目前流行的汇编系统中，当段内转移时，有些软件把该转移指令默认为近转移，从而使指令的偏移量用一个字来表示，于是生成3个字节的指令代码，但如果程序员自己清楚转移的幅度在一个短转移的范围之内，那么，可用前置short的办法来告诉汇编程序，让它产生2个字节的指令代码。</p>
<p>比如：如果程序员知道在上例中的标号next2离“JMP next2”指令的偏移量不会超过127，那么，可用下面的转移方式来省掉一个字节的指令代码。</p>
<p>next2: …</p>
<p>JMP short next2 ;生成2个字节的转移指令，从而节省一个字节</p>
<h3 id="2、条件转移指令-Transfer-Conditionally"><a href="#2、条件转移指令-Transfer-Conditionally" class="headerlink" title="2、条件转移指令(Transfer Conditionally)"></a>2、条件转移指令(Transfer Conditionally)</h3><p>条件转移指令是一组极其重要的转移指令，它根据标志寄存器中的一个(或多个)标志位来决定是否需要转移，这就为实现多功能程序提供了必要的手段。微机的指令系统提供了丰富的条件转移指令来满足各种不同的转移需要，在编程序时，要对它们灵活运用。</p>
<p>条件转移指令又分三大类：基于无符号数的条件转移指令、基于有符号数的条件转移指令和基于特殊算术标志位的条件转移指令。</p>
<p><strong>无符号数的条件转移指令(Jumps Based on Unsigned (Logic) Data)</strong></p>
<table>
<thead>
<tr>
<th>指令的助忆符</th>
<th>检测的转移条件</th>
<th>功能描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>JE/JZ</td>
<td>ZF=1</td>
<td>Jump Equal or Jump Zero</td>
</tr>
<tr>
<td>JNE/JNZ</td>
<td>ZF=0</td>
<td>Jump Not Equal or Jump Not Zero</td>
</tr>
<tr>
<td>JA/JNBE</td>
<td>CF=0 and ZF=0</td>
<td>Jump Above or Jump Not Below or Equal</td>
</tr>
<tr>
<td>JAE/JNB</td>
<td>CF=0</td>
<td>Jump Above or Equal or Jump Not Below</td>
</tr>
<tr>
<td>JB/JNAE</td>
<td>CF=1</td>
<td>Jump Below or Jump Not Above or Equal</td>
</tr>
<tr>
<td>JBE/JNA</td>
<td>CF=1 or AF=1</td>
<td>Jump Below or Equal or Jump Not Above</td>
</tr>
</tbody>
</table>
<p><strong>有符号数的条件转移指令(Jumps Based on Signed (Arithmetic) Data)</strong></p>
<table>
<thead>
<tr>
<th>指令的助忆符</th>
<th>检测的转移条件</th>
<th>功能描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>JE/JZ</td>
<td>ZF=1</td>
<td>Jump Equal or Jump Zero</td>
</tr>
<tr>
<td>JNE/JNZ</td>
<td>ZF=0</td>
<td>Jump Not Equal or Jump Not Zero</td>
</tr>
<tr>
<td>JG/JNLE</td>
<td>ZF=0 and SF=OF</td>
<td>Jump Greater or Jump Not Less or Equal</td>
</tr>
<tr>
<td>JGE/JNL</td>
<td>SF=OF</td>
<td>Jump Greater or Equal or Jump Not Less</td>
</tr>
<tr>
<td>JL/JNGE</td>
<td>SF≠OF</td>
<td>Jump Less or Jump Not Greater or Equal</td>
</tr>
<tr>
<td>JLE/JNG</td>
<td>ZF=1 or SF≠OF</td>
<td>Jump Less or Equal or Jump Not Greater</td>
</tr>
</tbody>
</table>
<p><strong>特殊算术标志位的条件转移指令(Jumps Based on Special Arithmetic Tests)</strong></p>
<table>
<thead>
<tr>
<th>指令的助忆符</th>
<th>检测的转移条件</th>
<th>功能描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>JC</td>
<td>CF=1</td>
<td>Jump Carry</td>
</tr>
<tr>
<td>JNC</td>
<td>CF=0</td>
<td>Jump Not Carry</td>
</tr>
<tr>
<td>JO</td>
<td>OF=1</td>
<td>Jump Overflow</td>
</tr>
<tr>
<td>JNO</td>
<td>OF=0</td>
<td>Jump Not Overflow</td>
</tr>
<tr>
<td>JP/JPE</td>
<td>PF=1</td>
<td>Jump Parity or Jump Parity Even</td>
</tr>
<tr>
<td>JNP/JPO</td>
<td>PF=0</td>
<td>Jump Not Parity or Jump Parity Odd</td>
</tr>
<tr>
<td>JS</td>
<td>SF=1</td>
<td>Jump Sign (negative)</td>
</tr>
<tr>
<td>JNS</td>
<td>SF=0</td>
<td>Jump No Sign (positive)</td>
</tr>
</tbody>
</table>
<p><strong>例5.15 编写一程序段，它把寄存器AX-BX的绝对值存入BX中。</strong></p>
<p>解：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">next: …</span><br><span class="line">SUB BX, AX</span><br><span class="line">JNS next</span><br><span class="line">NEG BX</span><br><span class="line">…</span><br></pre></td></tr></table></figure>
<p><strong>例5.16 已知一个字节变量char，试编写一程序段，把其所存的大写字母变成小写字母。</strong></p>
<p>解：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">next: …</span><br><span class="line">char  DB  &apos;F&apos;    ;变量说明</span><br><span class="line">…</span><br><span class="line">MOV AL, char</span><br><span class="line">CMP AL, &apos;A&apos;</span><br><span class="line">JB   next      ;注意：字符是无符号数，不要使用指令JL </span><br><span class="line">CMP AL, &apos;Z&apos;</span><br><span class="line">JA   next</span><br><span class="line">ADD char, 20H  ;小写字母比大写字母的ASCII码大20H </span><br><span class="line">…</span><br></pre></td></tr></table></figure>
<p>如果不知道(或忘了)大小写字母ASCII码之间的关系，那么，可用数值表达式’a’-‘A’、’b’-‘B’、…、’z’-‘Z’等来代替具体的数值20H。</p>
<p><strong>例5.17 编写一段程序，完成下面计算公式，其中：变量X和Y都是字类型。</strong></p>
<p>解：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">…</span><br><span class="line">X    DW      ;变量说明</span><br><span class="line">Y    DW  ?</span><br><span class="line">… </span><br><span class="line">MOV  AX, X</span><br><span class="line">MOV BX, AX   ;用BX来临时存放计算结果</span><br><span class="line">CMP  AX, 0</span><br><span class="line">JLE   setdata</span><br><span class="line">CMP  AX, 500</span><br><span class="line">JG   case3</span><br><span class="line">ADD  BX, 100D? ;BX=X+100</span><br><span class="line">JMP   setdata</span><br><span class="line">next:   SUB BX, 50D  ;BX=X-50</span><br><span class="line">setdata: MOV Y, BX    ;把计算结果赋给变量Y</span><br><span class="line">…</span><br></pre></td></tr></table></figure>
<p><strong>例5.18 下面循环体的指令代码字节数超过128，试改写该循环。</strong><br>…</p>
<p>MOV　CX, COUNT ;给循环计数器赋初值(＞0)</p>
<p>again: 循环体指令序列 ;循环体的首地址偏移量大于128</p>
<p>LOOP　again</p>
<p>解：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"> …</span><br><span class="line"> MOV　CX, COUNT</span><br><span class="line"> again:   循环体指令序列</span><br><span class="line"> DEC　CX</span><br><span class="line">JNZ　again  ;把LOOP指令改为条件转移指令</span><br></pre></td></tr></table></figure>
<h2 id="5-2-10-条件设置字节指令"><a href="#5-2-10-条件设置字节指令" class="headerlink" title="5.2.10 条件设置字节指令"></a>5.2.10 条件设置字节指令</h2><p>条件设置字节指令(Set Byte Conditionally)是80386及其以后CPU所具有的一组指令。它们在测试条件方面与条件转移是一致的，但在功能方面，它们不是转移，而是根据测试条件的值来设置其字节操作数的内容为1或0。</p>
<p>条件设置字节指令的一般格式如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">SETnn　Reg/Mem　　　　;80386+</span><br></pre></td></tr></table></figure>
<p>其中：nn是表示测试条件的(见表5.4)，操作数只能是8位寄存器或一个字节单元。</p>
<p>这组指令的执行不影响任何标志位。</p>
<p><strong>表5.4 条件设置字节指令列表</strong></p>
<table>
<thead>
<tr>
<th>指令的助忆符</th>
<th>操作数和检测条件之间的关系</th>
</tr>
</thead>
<tbody>
<tr>
<td>SETZ/SETE</td>
<td>Reg/Mem = ZF</td>
</tr>
<tr>
<td>SETNZSETNE</td>
<td>Reg/Mem = notZF</td>
</tr>
<tr>
<td>SETS</td>
<td>Reg/Mem = SF</td>
</tr>
<tr>
<td>SETNS</td>
<td>Reg/Mem = not SF</td>
</tr>
<tr>
<td>SETO</td>
<td>Reg/Mem = OF</td>
</tr>
<tr>
<td>SETNO</td>
<td>Reg/Mem = not OF</td>
</tr>
<tr>
<td>SETP/SETPE</td>
<td>Reg/Mem = PF</td>
</tr>
<tr>
<td>SETNP/SETPO</td>
<td>Reg/Mem = not PF</td>
</tr>
<tr>
<td>SETC/SETB/SETNAE</td>
<td>Reg/Mem = CF</td>
</tr>
<tr>
<td>SETNC/SETB/SETAE</td>
<td>Reg/Mem = not CF</td>
</tr>
<tr>
<td>SETNA/SETBE</td>
<td>Reg/Mem = (CF or ZF)</td>
</tr>
<tr>
<td>SETA/SETNBE</td>
<td>Reg/Mem = not (CF or ZF)</td>
</tr>
<tr>
<td>SETL/SETNGE</td>
<td>Reg/Mem = (SF xor OF)</td>
</tr>
<tr>
<td>SETNL/SETGE</td>
<td>Reg/Mem = not (SF xor OF)</td>
</tr>
<tr>
<td>SETLE/SETNG</td>
<td>Reg/Mem = (SF xor OF) or ZF</td>
</tr>
<tr>
<td>SETNLE/SETG</td>
<td>Reg/Mem = not ((SF xor OF) or ZF)</td>
</tr>
</tbody>
</table>
<p>例5.19 编写程序段：检测寄存器EAX的8个16进制中有几个0H，并把统计结果存入BH中。</p>
<p>解：</p>
<p>方法1：用条件转移指令来实现</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">XOR    BH, BH</span><br><span class="line">MOV   CX, 8   ;测试寄存器EAX——8次</span><br><span class="line">again:   TEST   AL, 0FH ;测试低四位二进制是否为0H</span><br><span class="line">JNZ next</span><br><span class="line">INC BH</span><br><span class="line">next:    ROR    EAX, 4  ;循环向右移四位，为测试高四位作准备</span><br><span class="line">LOOP   again</span><br></pre></td></tr></table></figure>
<p>方法2：用条件设置字节指令来实现</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"> XOR    BH, BH</span><br><span class="line"> MOV   CX, 8   ;测试寄存器EAX——8次</span><br><span class="line"> again:   TEST   AL, 0FH ;测试低四位二进制是否为0H</span><br><span class="line"> SETZ   BL  ;如果AL的低四位是0，则BL置为1，否则，BL为0</span><br><span class="line"> ADD    BH, BL</span><br><span class="line"> ROR    EAX, 4</span><br><span class="line">LOOP   again</span><br></pre></td></tr></table></figure>
<h2 id="5-2-11-字符串操作指令"><a href="#5-2-11-字符串操作指令" class="headerlink" title="5.2.11 字符串操作指令"></a>5.2.11 字符串操作指令</h2><p>字符串操作指令的实质是对一片连续存储单元进行处理，这片存储单元是由隐含指针DS:SI或ES:DI来指定的。字符串操作指令可对内存单元按字节、字或双字进行处理，并能根据操作对象的字节数使变址寄存器SI(和DI)增减1、2或4。具体规定如下：</p>
<p>(1)、当DF=0时，变址寄存器SI(和DI)增加1、2或4；</p>
<p>(2)、当DF=1时，变址寄存器SI(和DI)减少1、2或4。</p>
<p>在后面各指令中，有关变址寄存器都按上述规定进行增减，不再一一说明。</p>
<h3 id="1、取字符串数据指令-Load-String-Instruction"><a href="#1、取字符串数据指令-Load-String-Instruction" class="headerlink" title="1、取字符串数据指令(Load String Instruction)"></a>1、取字符串数据指令(Load String Instruction)</h3><p>从由指针DS:SI所指向的内存单元开始，取一个字节、字或双字进入AL、AX或EAX中，并根据标志位DF对寄存器SI作相应增减。该指令的执行不影响任何标志位。</p>
<p>指令的格式：LODS  地址表达式</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">LODSB/LODSW</span><br><span class="line">LODSD　　　　　　　　　　;80386+</span><br></pre></td></tr></table></figure>
<p>在指令LODS中，它会根据其地址表达式的属性来决定读取一个字节、字或双字。即：当该地址表达式的属性为字节、字或双字时，将从指针DS:SI处读一个字节到AL中，或读一个字到AX，或读一个双字到EAX中，与此同时，SI还将分别增减1，2或4。</p>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image001_0081.gif" alt></p>
<center><strong>图5.15 取字符串数据指令的功能示意图</strong></center>

<p>其它字符串指令中的“地址表达式”作用与此类似，将不再说明。</p>
<h3 id="2、置字符串数据指令-Store-String-Instruction"><a href="#2、置字符串数据指令-Store-String-Instruction" class="headerlink" title="2、置字符串数据指令(Store String Instruction)"></a>2、置字符串数据指令(Store String Instruction)</h3><p>该指令是把寄存器AL、AX或EAX中的值存于以指针ES:DI所指向内存单元为起始的一片存储单元里，并根据标志位DF对寄存器DI作相应增减。该指令不影响任何标志位。</p>
<p>指令的格式：STOS  地址表达式</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"> STOSB/STOSW</span><br><span class="line">STOSD　　　　　　;80386+</span><br></pre></td></tr></table></figure>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image002_0023.gif" alt="图5.16 置字符串数据指令的功能示意图"></p>
<center><strong>图5.16 置字符串数据指令的功能示意图</strong></center>

<h3 id="3、字符串传送指令-Move-String-Instruction"><a href="#3、字符串传送指令-Move-String-Instruction" class="headerlink" title="3、字符串传送指令(Move String Instruction)"></a>3、字符串传送指令(Move String Instruction)</h3><p>该指令是把指针DS:SI所指向的字节、字或双字传送给指针ES:DI所指向内存单元，并根据标志位DF对寄存器DI和SI作相应增减。该指令的执行不影响任何标志位。</p>
<p>指令的格式：MOVS  地址表达式1, 地址表达式2</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">MOVSB/MOVSW </span><br><span class="line"> MOVSD　　　　　　;80386+</span><br></pre></td></tr></table></figure>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image003_0011.gif" alt></p>
<center><strong>图5.17 字符串传送指令的功能示意图</strong></center>

<h3 id="4、输入字符串指令-Input-String-Instruction"><a href="#4、输入字符串指令-Input-String-Instruction" class="headerlink" title="4、输入字符串指令(Input String Instruction)"></a>4、输入字符串指令(Input String Instruction)</h3><p>该指令是从某一指定的端口接受一个字符串，并存入一片存储单元之中。输入端口由DX指定，存储单元的首地址和读入数据的个数分别由ES:DI和CX来确定。在指令的执行过程中，还根据标志位DF对寄存器DI作相应增减。该指令不影响任何标志位。</p>
<p>与指令有关的操作数ES、DI、DX和CX等都是隐含操作数。</p>
<p>指令的格式：INS  地址表达式</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">INSB/INSW </span><br><span class="line"> INSD　　　　　　　;80286+</span><br></pre></td></tr></table></figure>
<h3 id="5、输出字符串指令-Output-String-Instruction"><a href="#5、输出字符串指令-Output-String-Instruction" class="headerlink" title="5、输出字符串指令(Output String Instruction)"></a>5、输出字符串指令(Output String Instruction)</h3><p>该指令是把一个字符串输入到指定的输出端口中。输出端口由DX指定，其输出数据的首地址和个数分别由DS:SI和CX来确定。在指令的执行过程中，还根据标志位DF对寄存器SI作相应增减。该指令的执行不影响任何标志位。</p>
<p>与指令有关的操作数DS、SI、DX和CX等都是隐含操作数。</p>
<p>指令的格式：OUTS  地址表达式</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">OUTSB/OUTSW </span><br><span class="line"> OUTSD　　　　　　;80286+</span><br></pre></td></tr></table></figure>
<h3 id="6、字符串比较指令-Compare-String-Instruction"><a href="#6、字符串比较指令-Compare-String-Instruction" class="headerlink" title="6、字符串比较指令(Compare String Instruction)"></a>6、字符串比较指令(Compare String Instruction)</h3><p>该指令是把指针DS:SI和ES:DI所指向字节、字或双字的值相减，并用所得到的差来设置有关的标志位。与此同时，变址寄存器SI和DI也将根据标志位DF的值作相应增减。</p>
<p>指令的格式：CMPS　地址表达式1, 地址表达式2</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">CMPSB/CMPSW </span><br><span class="line"> CMPSD　　　　　　;80386+</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：AF、CF、OF、PF、SF和ZF</p>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image004_0002.gif" alt></p>
<center><strong>图5.18 字符串比较指令的功能示意图</strong></center>

<h3 id="7、字符串扫描指令-Scan-String-Instruction"><a href="#7、字符串扫描指令-Scan-String-Instruction" class="headerlink" title="7、字符串扫描指令(Scan String Instruction)"></a>7、字符串扫描指令(Scan String Instruction)</h3><p>该指令是用指针ES:DI所指向字节、字或双字的值与相应的AL、AX或EAX的值相减，用所得到的差来设置有关标志位。与此同时，变址寄存器DI还将根据标志位DF的值进行增减。</p>
<p>指令的格式：SCAS　地址表达式1</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">SCASB/SCASW</span><br><span class="line"> SCASD　　　　　　;80386+</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：AF、CF、OF、PF、SF和ZF</p>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image005_0001.gif" alt></p>
<center><strong>图5.19 字符串扫描指令的功能示意图</strong></center>

<h3 id="8、重复字符串操作指令-Repeat-String-Instruction"><a href="#8、重复字符串操作指令-Repeat-String-Instruction" class="headerlink" title="8、重复字符串操作指令(Repeat String Instruction)"></a>8、重复字符串操作指令(Repeat String Instruction)</h3><p>前面介绍了七种不同的字符串操作指令：取字符串数据、置字符串数据、字符串传送、输入字符串、输出字符串、字符串比较和字符串扫描等指令，所叙述是这些指令执行一次所具有的功能。但我们知道：每个字符串通常会有多个字符的，所以，就需要重复执行这些字符串操作指令。为了满足这种需求，指令系统提供了一组重复前缀指令。</p>
<p>虽然在这些字符串指令的前面都可以添加一个重复前缀指令，但由于指令执行结果的差异，对某个具体的字符串指令又不用重复前缀指令而改用其它循环来实现重复的需要。</p>
<p>重复字符串操作指令对标志位的影响是由被重复的字符串操作指令来决定。</p>
<p><strong>重复前缀指令REP(Repeat String Instruction)</strong></p>
<p>重复前缀指令是重复其后的字符串操作指令，重复的次数由CX来决定。其一般格式为：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">REP　LODS/LODSB/LODSW/LODSD</span><br><span class="line"></span><br><span class="line">REP　STOS/STOSB/STOSW/STOSD</span><br><span class="line"></span><br><span class="line">REP　MOVS/MOVSB/MOVSW/MOVSD</span><br><span class="line"></span><br><span class="line">REP　INS/ INSB/INSW/INSD</span><br><span class="line"></span><br><span class="line">REP　OUTS/OUTSB/OUTSW/OUTSD</span><br></pre></td></tr></table></figure>
<p>重复前缀指令的执行步骤如下：</p>
<p>(1)、判断：CX=0；</p>
<p>(2)、如果CX=0，则结束重复操作，执行程序中的下一条指令；</p>
<p>(3)、否则，CX=CX-1(不影响有关标志位)，并执行其后的字符串操作指令，在该指令执行完后，再转到步骤(1)。</p>
<p>从上面的重复前缀指令格式来看，虽然我们可以使用重复取字符串数据指令(第一组指令)，但可能会因为指令的执行结果而在程序中几乎不被使用。</p>
<p><strong>例5.20 编写一段程序，计算字符串“12345abcdefgh”中字符的ASCII之和。</strong></p>
<p>解：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">…</span><br><span class="line">MESS DB  &apos;12345abcdefgh&apos;    ;在数据段中进行变量说明</span><br><span class="line">…</span><br><span class="line">MOV AX, SEG MESS</span><br><span class="line">MOV DS, AX</span><br><span class="line">LEA  SI, MESS            ;用DS:SI来指向字符串的首地址</span><br><span class="line">MOV CX, 13D             ;重复次数</span><br><span class="line">XOR  BX, BX              ;置求和的初值为0</span><br><span class="line">REP  LODSB</span><br><span class="line">…</span><br></pre></td></tr></table></figure>
<p>虽然指令“REP  LODSB”能从字符串中取出每个字符，但它是在一条指令中完成的，程序的其它指令根本无法处理每次取出的数据，指令的执行结果是：AL只保存最后一次所取出的字符’h’的ASCII码。</p>
<p>所以，为了实现本例的要求，不能使用重复前缀指令，而要把指令“REP  LODSB”改写成如下四条指令：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">XOR  AH, AH              ;为后面的累加作准备 </span><br><span class="line"> again:  LODSB</span><br><span class="line"></span><br><span class="line"> ADD  BX, AX              ;AL是被取出的字符，AH已被清0 </span><br><span class="line"> LOOP again</span><br></pre></td></tr></table></figure>
<p><strong>条件重复前缀指令(Repeat String Conditionally)</strong></p>
<p>条件重复前缀指令与前面的重复前缀指令功能相类似，所不同的是：其重复次数不仅由CX来决定，而且还会由标志位ZF来决定。根据ZF所起的作用又分为二种：相等重复前缀指令REPE/REPZ和不等重复前缀指令REPE/REPZ。</p>
<p>A、相等重复前缀指令的一般格式为：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">REPE/REPZ　SCAS/SCASB/SCASW/SCASD </span><br><span class="line"> REPE/REPZ　CMPS/CMPSB/CMPSW/CMPSD</span><br></pre></td></tr></table></figure>
<p>该重复前缀指令的执行步骤如下：</p>
<p>(1)、判断条件：CX≠0 且 ZF=1；</p>
<p>(2)、如果条件不成立，则结束重复操作，执行程序中的下一条指令；</p>
<p>(3)、否则，CX=CX-1(不影响有关标志位)，并执行其后的字符串操作指令，在该指令执行完后，再转到步骤(1)。</p>
<p>B、不等重复前缀指令的一般格式为：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"> REPNE/REPNZ　SCAS/SCASB/SCASW/SCASD</span><br><span class="line">REPNE/REPNZ　CMPS/CMPSB/CMPSW/CMPSD</span><br></pre></td></tr></table></figure>
<p>该重复前缀指令的执行步骤如下：</p>
<p>(1)、判断条件：CX≠0 且 ZF=0；</p>
<p>(2)、如果条件不成立，则结束重复操作，执行程序中的下一条指令；</p>
<p>(3)、否则，CX=CX-1(不影响有关标志位)，并执行其后的字符串操作指令，在该指令执行完后，再转到步骤(1)。</p>
<h2 id="5-2-12-ASCII–BCD码运算调整指令"><a href="#5-2-12-ASCII–BCD码运算调整指令" class="headerlink" title="5.2.12 ASCII–BCD码运算调整指令"></a>5.2.12 ASCII–BCD码运算调整指令</h2><p>前面介绍的算术运算指令都是针对二进制数进行操作的指令，但对绝大多数人来说，十进制是最简单、熟悉的。为了方便按十进制数进行算术运算，指令系统专门提供了一组十进制运算调整指令。</p>
<p>虽然人们会觉得按十进制进行算术运算很自然，但计算机要化更多的时间来完成相应操作。在通常情况下，这组指令很少被程序员运用在实际的程序之中。所以，这组指令的使用率较低，可以根据需要有选择性地学习。</p>
<h3 id="1、ASCII码加调整指令AAA-Ascii-Adjust-After-Addition"><a href="#1、ASCII码加调整指令AAA-Ascii-Adjust-After-Addition" class="headerlink" title="1、ASCII码加调整指令AAA(Ascii Adjust After Addition)"></a>1、ASCII码加调整指令AAA(Ascii Adjust After Addition)</h3><p>该指令是用于调整AL之值，该值是二个ASCII码字节相加之和。具体的调整规则如下：</p>
<ul>
<li>若AL的低四位大于9，或标志位AF=1，则，AH=AH+1，AL=AL+6，并置AF和CF为1，否则，只置AF和CF为0；</li>
<li>清除AL的高四位。</li>
</ul>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image008_0001.gif" alt></p>
<center><strong>图5.20 AAA指令执行过程示意图</strong></center>

<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">AAA</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：AF和CF(OF、PF、SF和ZF等都是无定义)</p>
<p><strong>例5.21 编写一段程序，完成二个15位十进制数X和Y之和，并把计算结果存入X之中。假设数据X和Y都是以字符串形式表示的。</strong></p>
<p>解：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">…</span><br><span class="line">X    db　&quot;456407983123186&quot;    ;任意假设二个15位的大数</span><br><span class="line">Y    db　&quot;326676709587211&quot;</span><br><span class="line">…</span><br><span class="line">CLC</span><br><span class="line">MOV  SI, 14            ;用变址寄存器SI来从字符串的后面向前访问</span><br><span class="line">MOV  CX, 15           ;因为它们是二个15位十进制数</span><br><span class="line">loop1: MOV  AL,  X[SI]</span><br><span class="line">ADC  AL, Y[SI]         ;把被加数加上</span><br><span class="line">AAA</span><br><span class="line">MOV  X[SI], AL</span><br><span class="line">DEC  SI</span><br><span class="line">LOOP loop1            ;15位十进制数相加完毕</span><br><span class="line">LEA  BX, X            ;下面5条指令是把X中的数据变成对应的字符</span><br><span class="line">MOV  CX, 15</span><br><span class="line">loop2: ADD  byte ptr [BX], &apos;0&apos;</span><br><span class="line">INC  BX</span><br><span class="line">LOOP loop2</span><br><span class="line">…</span><br></pre></td></tr></table></figure>
<p>从上例可以看出，其实任意位的十进制数也都是可以的，只要改变CX的值即可。</p>
<h3 id="2、ASCII码减调整指令AAS-Ascii-Adjust-After-Subtraction"><a href="#2、ASCII码减调整指令AAS-Ascii-Adjust-After-Subtraction" class="headerlink" title="2、ASCII码减调整指令AAS(Ascii Adjust After Subtraction)"></a>2、ASCII码减调整指令AAS(Ascii Adjust After Subtraction)</h3><p>该指令是用于调整AL之值，该值是二个ASCII码字节相减之差。具体的调整规则如下：</p>
<ul>
<li>若AL的低四位大于9，或标志位CF=1，则，AH=AH-1，AL=AL-6，并置AF和CF为1，否则，只置AF和CF为0；</li>
<li>清除AL的高四位。</li>
</ul>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">AAS</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：AF和CF(OF、PF、SF和ZF等都是无定义)</p>
<p><img src="http://www.iteedu.com/plang/asm/asmhbyychxshj/images/clip_image009_0000.gif" alt></p>
<center><strong>图5.21 AAS指令执行过程示意图</strong></center>

<h3 id="3、ASCII码乘调整指令AAM-Ascii-Adjust-After-Multiplication"><a href="#3、ASCII码乘调整指令AAM-Ascii-Adjust-After-Multiplication" class="headerlink" title="3、ASCII码乘调整指令AAM(Ascii Adjust After Multiplication)"></a>3、ASCII码乘调整指令AAM(Ascii Adjust After Multiplication)</h3><p>该指令是用于调整寄存器AL之值，该值是由二个单BCD码字节用无符号乘指令MUL所得的积。其调整规则如下：</p>
<p>AH←AL/10(商)，AL←AL%10(余数)</p>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">AAM</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：PF、SF和ZF(AF、CF和OF等都是无定义)</p>
<p>例如：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">MOV　AL, 9</span><br><span class="line">MOV　BL, 8</span><br><span class="line">MUL　BL　　　　　　　;AL=72D</span><br><span class="line">AAM　　　　　　　　　;AH=7, AL=2</span><br></pre></td></tr></table></figure>
<h3 id="4、ASCII码除调整指令AAD-Ascii-Adjust-After-Division"><a href="#4、ASCII码除调整指令AAD-Ascii-Adjust-After-Division" class="headerlink" title="4、ASCII码除调整指令AAD(Ascii Adjust After Division)"></a>4、ASCII码除调整指令AAD(Ascii Adjust After Division)</h3><p>该指令是在作除法前用于调整寄存器AH和AL之值，它是把二个寄存器中单BCD码组成一个十进制数值，为下面的除法作准备的。其调整规则如下：</p>
<p>AL←AH*10+AL，AH←0</p>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">AAD</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：PF、SF和ZF(AF、CF和OF等都是无定义)</p>
<p>例如：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">MOV　AX, 0502H</span><br><span class="line">MOV　BL, 10D</span><br><span class="line">AAD　　　　　　　　　;AH=0, AL=52D</span><br><span class="line">DIV　 BL　　　　　　　;AH=2(余数), AL=5(商)</span><br></pre></td></tr></table></figure>
<h3 id="5、十进制数加调整指令DAA-Decimal-Adjust-After-Addition"><a href="#5、十进制数加调整指令DAA-Decimal-Adjust-After-Addition" class="headerlink" title="5、十进制数加调整指令DAA(Decimal Adjust After Addition)"></a>5、十进制数加调整指令DAA(Decimal Adjust After Addition)</h3><p>该指令是用于调整AL的值，该值是由指令ADD或ADC运算二个压缩型BCD码所得到的结果。压缩型BCD码是一个字节存放二个BCD码，低四位和高四位都是一个BCD码。</p>
<p>其调整规则如下：</p>
<ul>
<li>如果AL的低四位大于9，或标志位AF=1，那么，AL=AL+6，并置AF=1；</li>
<li>如果AL的高四位大于9，或CF=1，那么，AL=AL+60H，并置CF=1；</li>
<li>如果以上两点都不成立，则，清除标志位AF和CF。</li>
</ul>
<p>经过调整后，AL的值仍是压缩型BCD码，即：二个压缩型BCD码相加，并进行调整后，得到的结果还是压缩型BCD码。</p>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">DAA</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：AF、CF、PF、SF和ZF(OF无定义)</p>
<p>例如：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">MOV　AL, 43H</span><br><span class="line">MOV　BL, 29H</span><br><span class="line">ADD　AL, BL　　　　　;AL=6BH，其不是压缩型的BCD码，因为低四位&apos;B&apos;不是BCD码 </span><br><span class="line">DAA　　　　　　　　　;调整后，AL=72H，这是压缩型的BCD码，也有：43+29=72</span><br></pre></td></tr></table></figure>
<h3 id="6、十进制数减调整指令DAS-Decimal-Adjust-After-Subtraction"><a href="#6、十进制数减调整指令DAS-Decimal-Adjust-After-Subtraction" class="headerlink" title="6、十进制数减调整指令DAS(Decimal Adjust After Subtraction)"></a>6、十进制数减调整指令DAS(Decimal Adjust After Subtraction)</h3><p>该指令也是用于调整AL的值，该值是由指令SUB或SBB运算二个压缩型BCD码所得到的结果。其调整规则如下：</p>
<ul>
<li>如果AL的低四位大于9，或标志位AF=1，那么，AL=AL-6，并置AF=1；</li>
<li>如果AL的高四位大于9，或CF=1，那么，AL=AL-60H，并置CF=1；</li>
<li>如果以上两点都不成立，则，清除标志位AF和CF。</li>
</ul>
<p>经过调整后，AL的值仍是压缩型BCD码，即：二个压缩型BCD码相减，并进行调整后，得到的结果还是压缩型BCD码。</p>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">DAS</span><br></pre></td></tr></table></figure>
<p>受影响的标志位：AF、CF、PF、SF和ZF(OF无定义)</p>
<p>例如：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"> MOV　AL, 43H</span><br><span class="line"> MOV　BL, 29H</span><br><span class="line"> SUB　AL, BL　　　　;AL=1AH，其不是压缩型的BCD码，因为低四位&apos;A&apos;不是BCD码</span><br><span class="line">DAS　　　　　　　　;调整后，AL=14H，这是压缩型的BCD码，也有：43-29=14</span><br></pre></td></tr></table></figure>
<h2 id="5-2-13-处理器指令"><a href="#5-2-13-处理器指令" class="headerlink" title="5.2.13 处理器指令"></a>5.2.13 处理器指令</h2><p>处理器指令是一组控制CPU工作方式的指令。这组指令的使用频率不高。</p>
<h3 id="1、空操作指令NOP-No-Operation-Instruction"><a href="#1、空操作指令NOP-No-Operation-Instruction" class="headerlink" title="1、空操作指令NOP(No Operation Instruction)"></a>1、空操作指令NOP(No Operation Instruction)</h3><p>该指令没有的显式操作数，主要起延迟下一条指令的执行。通常用执行指令“XCHG AX, AX”来代表它的执行。NOP指令的执行不影响任何标志位。</p>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">NOP</span><br></pre></td></tr></table></figure>
<h3 id="2、等待指令-WAIT-Put-Processor-in-Wait-State-Instruction"><a href="#2、等待指令-WAIT-Put-Processor-in-Wait-State-Instruction" class="headerlink" title="2、等待指令 WAIT(Put Processor in Wait State Instruction)"></a>2、等待指令 WAIT(Put Processor in Wait State Instruction)</h3><p>该指令使CPU处于等待状态，直到协处理器(Coprocessor)完成运算，并用一个重启信号唤醒CPU为止。该指令的执行不影响任何标志位。</p>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">WAIT</span><br></pre></td></tr></table></figure>
<h3 id="3、暂停指令-HLT-Enter-Halt-State-Instruction"><a href="#3、暂停指令-HLT-Enter-Halt-State-Instruction" class="headerlink" title="3、暂停指令 HLT(Enter Halt State Instruction)"></a>3、暂停指令 HLT(Enter Halt State Instruction)</h3><p>在等待中断信号时，该指令使CPU处于暂停工作状态，CS:IP指向下一条待执行的指令。当产生了中断信号，CPU把CS和IP压栈，并转入中断处理程序。在中断处理程序执行完后，中断返回指令IRET弹出IP和CS，并唤醒CPU执行下条指令。</p>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">HLT</span><br></pre></td></tr></table></figure>
<p>指令的执行不影响任何标志位。</p>
<h3 id="4、封锁数据指令-LOCK-Lock-Bus-Instruction"><a href="#4、封锁数据指令-LOCK-Lock-Bus-Instruction" class="headerlink" title="4、封锁数据指令 LOCK(Lock Bus Instruction)"></a>4、封锁数据指令 LOCK(Lock Bus Instruction)</h3><p>该指令是一个前缀指令形式，在其后面跟一个具体的操作指令。LOCK指令可以保证是在其后指令执行过程中，禁止协处理器修改数据总线上的数据，起到独占总线的作用。该指令的执行不影响任何标志位。</p>
<p>指令的格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">LOCK INSTRUCTION</span><br></pre></td></tr></table></figure>

      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/limh/tags/教程/" rel="tag"># 教程</a>
          
        </div>
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/limh/2015/04/01/asm21/" rel="next" title="5.1 汇编语言指令格式">
                <i class="fa fa-chevron-left"></i> 5.1 汇编语言指令格式
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/limh/2015/04/01/asm23/" rel="prev" title="6.1 源程序的基本组成">
                6.1 源程序的基本组成 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  
    <div class="comments" id="comments">
      <div id="SOHUCS"></div>
    </div>

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image" src="/limh/images/avatar.jpg" alt="土逗牛肉">
            
              <p class="site-author-name" itemprop="name">土逗牛肉</p>
              <p class="site-description motion-element" itemprop="description"></p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/limh/archives/">
              
                  <span class="site-state-item-count">255</span>
                  <span class="site-state-item-name">日志</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                <a href="/limh/categories/index.html">
                  <span class="site-state-item-count">8</span>
                  <span class="site-state-item-name">分类</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-tags">
                <a href="/limh/tags/index.html">
                  <span class="site-state-item-count">7</span>
                  <span class="site-state-item-name">标签</span>
                </a>
              </div>
            

          </nav>

          

          
            <div class="links-of-author motion-element">
                
                  <span class="links-of-author-item">
                    <a href="https://github.com/limhGeek" target="_blank" title="GitHub">
                      
                        <i class="fa fa-fw fa-github"></i>GitHub</a>
                  </span>
                
                  <span class="links-of-author-item">
                    <a href="mailto:1591054297@qq.com" target="_blank" title="E-Mail">
                      
                        <i class="fa fa-fw fa-envelope"></i>E-Mail</a>
                  </span>
                
                  <span class="links-of-author-item">
                    <a href="https://www.jianshu.com/u/f73b243e7cc9" target="_blank" title="简书">
                      
                        <i class="fa fa-fw fa-user-circle-o"></i>简书</a>
                  </span>
                
            </div>
          

          
          

          
          

          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#5-2-1-数据传送指令"><span class="nav-number">1.</span> <span class="nav-text">5.2.1 数据传送指令</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1、传送指令MOV-Move-Instruction"><span class="nav-number">1.1.</span> <span class="nav-text">1、传送指令MOV(Move Instruction)</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#源操作数是寄存器"><span class="nav-number">1.1.1.</span> <span class="nav-text">源操作数是寄存器</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#源操作数是存储单元"><span class="nav-number">1.1.2.</span> <span class="nav-text">源操作数是存储单元</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#源操作数是立即数"><span class="nav-number">1.1.3.</span> <span class="nav-text">源操作数是立即数</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2、传送—填充指令-Move-and-Fill-Instruction"><span class="nav-number">1.2.</span> <span class="nav-text">2、传送—填充指令(Move-and-Fill Instruction)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3、交换指令XCHG-Exchange-Instruction"><span class="nav-number">1.3.</span> <span class="nav-text">3、交换指令XCHG(Exchange Instruction)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4、取有效地址指令LEA-Load-Effective-Address"><span class="nav-number">1.4.</span> <span class="nav-text">4、取有效地址指令LEA(Load Effective Address)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#5、取段寄存器指令-Load-Segment-Instruction"><span class="nav-number">1.5.</span> <span class="nav-text">5、取段寄存器指令(Load Segment Instruction)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#6、堆栈操作指令-Stack-Operation-Instruction"><span class="nav-number">1.6.</span> <span class="nav-text">6、堆栈操作指令(Stack Operation Instruction)</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#1-、进栈操作"><span class="nav-number">1.6.1.</span> <span class="nav-text">1)、进栈操作</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-、出栈操作"><span class="nav-number">1.6.2.</span> <span class="nav-text">2)、出栈操作</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#7、转换指令XLAT-Translate-Instruction"><span class="nav-number">1.7.</span> <span class="nav-text">7、转换指令XLAT(Translate Instruction)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#8、I-O指令"><span class="nav-number">1.8.</span> <span class="nav-text">8、I/O指令</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-2-2-标志位操作指令"><span class="nav-number">2.</span> <span class="nav-text">5.2.2 标志位操作指令</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1-进位CF操作指令"><span class="nav-number">2.1.</span> <span class="nav-text">1.进位CF操作指令</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-方向位DF操作指令"><span class="nav-number">2.2.</span> <span class="nav-text">2.方向位DF操作指令</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-中断允许位IF操作指令"><span class="nav-number">2.3.</span> <span class="nav-text">3.中断允许位IF操作指令</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4-取标志位操作指令"><span class="nav-number">2.4.</span> <span class="nav-text">4.取标志位操作指令</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#5-标志位堆栈操作指令"><span class="nav-number">2.5.</span> <span class="nav-text">5.标志位堆栈操作指令</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#6-逻辑操作指令的小结"><span class="nav-number">2.6.</span> <span class="nav-text">6.逻辑操作指令的小结</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-2-3-算术运算指令"><span class="nav-number">3.</span> <span class="nav-text">5.2.3 算术运算指令</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1、加法指令"><span class="nav-number">3.1.</span> <span class="nav-text">1、加法指令</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2、减法指令"><span class="nav-number">3.2.</span> <span class="nav-text">2、减法指令</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3、乘法指令"><span class="nav-number">3.3.</span> <span class="nav-text">3、乘法指令</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4、除法指令"><span class="nav-number">3.4.</span> <span class="nav-text">4、除法指令</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#5、类型转换指令"><span class="nav-number">3.5.</span> <span class="nav-text">5、类型转换指令</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-2-4-逻辑运算指令"><span class="nav-number">4.</span> <span class="nav-text">5.2.4 逻辑运算指令</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1、逻辑与操作指令AND-Logical-AND-Instruction"><span class="nav-number">4.1.</span> <span class="nav-text">1、逻辑与操作指令AND(Logical AND Instruction)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2、逻辑或操作指令OR-Logical-OR-Instruction"><span class="nav-number">4.2.</span> <span class="nav-text">2、逻辑或操作指令OR(Logical OR Instruction)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3、逻辑非操作指令NOT-Logical-NOT-Instruction"><span class="nav-number">4.3.</span> <span class="nav-text">3、逻辑非操作指令NOT(Logical NOT Instruction)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4、逻辑异或操作指令XOR-Exclusive-OR-Instruction"><span class="nav-number">4.4.</span> <span class="nav-text">4、逻辑异或操作指令XOR(Exclusive OR Instruction)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#5、逻辑操作指令的小结"><span class="nav-number">4.5.</span> <span class="nav-text">5、逻辑操作指令的小结</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-2-5-移位操作指令"><span class="nav-number">5.</span> <span class="nav-text">5.2.5 移位操作指令</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1、算术移位指令"><span class="nav-number">5.1.</span> <span class="nav-text">1、算术移位指令</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2、逻辑移位指令"><span class="nav-number">5.2.</span> <span class="nav-text">2、逻辑移位指令</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3、双精度移位指令"><span class="nav-number">5.3.</span> <span class="nav-text">3、双精度移位指令</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4、循环移位指令"><span class="nav-number">5.4.</span> <span class="nav-text">4、循环移位指令</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#5、带进位的循环移位指令"><span class="nav-number">5.5.</span> <span class="nav-text">5、带进位的循环移位指令</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-2-6-位操作指令"><span class="nav-number">6.</span> <span class="nav-text">5.2.6 位操作指令</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1、位扫描指令-Bit-Scan-Instruction"><span class="nav-number">6.1.</span> <span class="nav-text">1、位扫描指令(Bit Scan Instruction)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2、位检测指令-Bit-Test-Instruction"><span class="nav-number">6.2.</span> <span class="nav-text">2、位检测指令(Bit Test Instruction)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3、检测位指令TEST-Test-Bits-Instruction"><span class="nav-number">6.3.</span> <span class="nav-text">3、检测位指令TEST(Test Bits Instruction)</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-2-7-比较运算指令"><span class="nav-number">7.</span> <span class="nav-text">5.2.7 比较运算指令</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1、比较指令CMP-Compare-Instruction"><span class="nav-number">7.1.</span> <span class="nav-text">1、比较指令CMP(Compare Instruction)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2、比较交换指令-Compare-And-Exchange-Instruction"><span class="nav-number">7.2.</span> <span class="nav-text">2、比较交换指令(Compare And Exchange Instruction)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3、字符串比较指令-Compare-String-Instruction"><span class="nav-number">7.3.</span> <span class="nav-text">3、字符串比较指令(Compare String Instruction)</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-2-8-循环指令"><span class="nav-number">8.</span> <span class="nav-text">5.2.8 循环指令</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1、循环指令-Loop-Until-Complete"><span class="nav-number">8.1.</span> <span class="nav-text">1、循环指令(Loop Until Complete)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2、相等或为零循环指令-Loop-While-Equal-or-Loop-While-Zero"><span class="nav-number">8.2.</span> <span class="nav-text">2、相等或为零循环指令(Loop While Equal or Loop While Zero)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3、不等或不为零循环指令-Loop-While-Not-Equal-or-Loop-While-Not-Zero"><span class="nav-number">8.3.</span> <span class="nav-text">3、不等或不为零循环指令(Loop While Not Equal or Loop While Not Zero)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4、循环计数器为零转指令-Jump-if-CX-ECX-is-Zero"><span class="nav-number">8.4.</span> <span class="nav-text">4、循环计数器为零转指令(Jump if CX/ECX is Zero)</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-2-9-转移指令"><span class="nav-number">9.</span> <span class="nav-text">5.2.9 转移指令</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1、无条件转移指令-Transfer-Unconditionally"><span class="nav-number">9.1.</span> <span class="nav-text">1、无条件转移指令(Transfer Unconditionally)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2、条件转移指令-Transfer-Conditionally"><span class="nav-number">9.2.</span> <span class="nav-text">2、条件转移指令(Transfer Conditionally)</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-2-10-条件设置字节指令"><span class="nav-number">10.</span> <span class="nav-text">5.2.10 条件设置字节指令</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-2-11-字符串操作指令"><span class="nav-number">11.</span> <span class="nav-text">5.2.11 字符串操作指令</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1、取字符串数据指令-Load-String-Instruction"><span class="nav-number">11.1.</span> <span class="nav-text">1、取字符串数据指令(Load String Instruction)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2、置字符串数据指令-Store-String-Instruction"><span class="nav-number">11.2.</span> <span class="nav-text">2、置字符串数据指令(Store String Instruction)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3、字符串传送指令-Move-String-Instruction"><span class="nav-number">11.3.</span> <span class="nav-text">3、字符串传送指令(Move String Instruction)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4、输入字符串指令-Input-String-Instruction"><span class="nav-number">11.4.</span> <span class="nav-text">4、输入字符串指令(Input String Instruction)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#5、输出字符串指令-Output-String-Instruction"><span class="nav-number">11.5.</span> <span class="nav-text">5、输出字符串指令(Output String Instruction)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#6、字符串比较指令-Compare-String-Instruction"><span class="nav-number">11.6.</span> <span class="nav-text">6、字符串比较指令(Compare String Instruction)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#7、字符串扫描指令-Scan-String-Instruction"><span class="nav-number">11.7.</span> <span class="nav-text">7、字符串扫描指令(Scan String Instruction)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#8、重复字符串操作指令-Repeat-String-Instruction"><span class="nav-number">11.8.</span> <span class="nav-text">8、重复字符串操作指令(Repeat String Instruction)</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-2-12-ASCII–BCD码运算调整指令"><span class="nav-number">12.</span> <span class="nav-text">5.2.12 ASCII–BCD码运算调整指令</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1、ASCII码加调整指令AAA-Ascii-Adjust-After-Addition"><span class="nav-number">12.1.</span> <span class="nav-text">1、ASCII码加调整指令AAA(Ascii Adjust After Addition)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2、ASCII码减调整指令AAS-Ascii-Adjust-After-Subtraction"><span class="nav-number">12.2.</span> <span class="nav-text">2、ASCII码减调整指令AAS(Ascii Adjust After Subtraction)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3、ASCII码乘调整指令AAM-Ascii-Adjust-After-Multiplication"><span class="nav-number">12.3.</span> <span class="nav-text">3、ASCII码乘调整指令AAM(Ascii Adjust After Multiplication)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4、ASCII码除调整指令AAD-Ascii-Adjust-After-Division"><span class="nav-number">12.4.</span> <span class="nav-text">4、ASCII码除调整指令AAD(Ascii Adjust After Division)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#5、十进制数加调整指令DAA-Decimal-Adjust-After-Addition"><span class="nav-number">12.5.</span> <span class="nav-text">5、十进制数加调整指令DAA(Decimal Adjust After Addition)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#6、十进制数减调整指令DAS-Decimal-Adjust-After-Subtraction"><span class="nav-number">12.6.</span> <span class="nav-text">6、十进制数减调整指令DAS(Decimal Adjust After Subtraction)</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-2-13-处理器指令"><span class="nav-number">13.</span> <span class="nav-text">5.2.13 处理器指令</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1、空操作指令NOP-No-Operation-Instruction"><span class="nav-number">13.1.</span> <span class="nav-text">1、空操作指令NOP(No Operation Instruction)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2、等待指令-WAIT-Put-Processor-in-Wait-State-Instruction"><span class="nav-number">13.2.</span> <span class="nav-text">2、等待指令 WAIT(Put Processor in Wait State Instruction)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3、暂停指令-HLT-Enter-Halt-State-Instruction"><span class="nav-number">13.3.</span> <span class="nav-text">3、暂停指令 HLT(Enter Halt State Instruction)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4、封锁数据指令-LOCK-Lock-Bus-Instruction"><span class="nav-number">13.4.</span> <span class="nav-text">4、封锁数据指令 LOCK(Lock Bus Instruction)</span></a></li></ol></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2019</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">土逗牛肉</span>

  
</div>


  <div class="powered-by">由 <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a> 强力驱动</div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">主题 &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Gemini</a> v5.1.4</div>




        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
	var str = GetUrlParam('height');
    if (str === '0'){
		document.getElementById('header').style.display = 'none';
		document.getElementById('comments').style.display = 'none';
		document.getElementById('footer').style.display = 'none';
		document.getElementsByClassName('post-footer').item(0).style.display = 'none'
	}
	
    function GetUrlParam(paraName) {
        var url = document.location.toString();
        var arrObj = url.split("?");

        if (arrObj.length > 1) {
            var arrPara = arrObj[1].split("&");
            var arr;

            for (var i = 0; i < arrPara.length; i++) {
                 arr = arrPara[i].split("=");

                if (arr != null && arr[0] === paraName) {
                    return arr[1];
                }
            }
            return "";
        } else {
            return "";
        }
    }
</script>









  












  
  
    <script type="text/javascript" src="/limh/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/limh/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/limh/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/limh/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/limh/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/limh/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  


  


  <script type="text/javascript" src="/limh/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/limh/js/src/motion.js?v=5.1.4"></script>



  
  


  <script type="text/javascript" src="/limh/js/src/affix.js?v=5.1.4"></script>

  <script type="text/javascript" src="/limh/js/src/schemes/pisces.js?v=5.1.4"></script>



  
  <script type="text/javascript" src="/limh/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/limh/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/limh/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  












  





  

  

  

  
  

  

  

  

</body>
</html>
